Search in sources :

Example 1 with PatchedClassWriter

use of com.newrelic.agent.util.asm.PatchedClassWriter in project newrelic-java-agent by newrelic.

the class InstrumentingClassLoader method transform.

@Override
protected byte[] transform(String className) throws Exception {
    byte[] classBytes = WeaveUtils.getClassBytesFromClassLoaderResource(className, this);
    if (classBytes == null) {
        return null;
    }
    final InstrumentationContext context = new InstrumentationContext(classBytes, null, null);
    new ClassReader(classBytes).accept(new ScalaTraitMatcher().newClassMatchVisitor(null, null, null, null, context), ClassReader.SKIP_FRAMES);
    // weave
    byte[] weaved = weave(className, classBytes, context.getSkipMethods(), new ClassWeavedListener() {

        @Override
        public void classWeaved(PackageWeaveResult weaveResult, ClassLoader classloader, ClassCache cache) {
            if (weaveResult.weavedClass()) {
                final String packageName = weaveResult.getValidationResult().getWeavePackage().getName();
                for (String originalName : weaveResult.getWeavedMethods().keySet()) {
                    for (Method method : weaveResult.getWeavedMethods().get(originalName)) {
                        context.addWeavedMethod(method, packageName);
                    }
                    ClassWeaverService.addTraceInformation(InstrumentingClassLoader.this.tracedWeaveInstrumentationDetails, packageName, context, weaveResult.getComposite(), originalName);
                }
                try {
                    Map<String, byte[]> annotationProxyClasses = weaveResult.getAnnotationProxyClasses();
                    if (!annotationProxyClasses.isEmpty()) {
                        // Special case for annotation weaving in order to support dynamic annotation proxies. We
                        // need to add the dynamic proxy classes that we created to the current classloader here
                        NewClassAppender.appendClasses(classloader, annotationProxyClasses);
                    }
                } catch (Exception e) {
                    Agent.LOG.log(Level.FINE, e, "Unable to add annotation proxy classes");
                }
            }
        }
    });
    // trace
    if (weaved != null) {
        classBytes = weaved;
    }
    ClassReader reader = new ClassReader(classBytes);
    if (weaved == null) {
        // process trace annotations for non-weaved code
        reader.accept(new SimpleTraceMatchVisitor(null, context), ClassReader.EXPAND_FRAMES);
    }
    if (!context.isTracerMatch()) {
        if (weaved != null) {
            // printClass(className, weaved);
            return weaved;
        }
        return null;
    }
    NoticeSqlVisitor noticeSqlVisitor = new NoticeSqlVisitor(WeaveUtils.ASM_API_LEVEL);
    // find the noticeSql calls
    reader.accept(noticeSqlVisitor, ClassReader.SKIP_FRAMES);
    String internalClassName = className.replace('.', '/');
    ClassWriter writer = new PatchedClassWriter(ClassWriter.COMPUTE_FRAMES, context.getClassResolver(this));
    ClassVisitor cv = writer;
    cv = new TraceClassVisitor(cv, internalClassName, context, noticeSqlVisitor.getNoticeSqlMethods());
    cv = new ClassVisitor(WeaveUtils.ASM_API_LEVEL, cv) {

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            if (version < 49 || version > 100) {
                // Some weird Apache classes have really large versions.
                version = WeaveUtils.RUNTIME_MAX_SUPPORTED_CLASS_VERSION;
            }
            super.visit(version, access, name, signature, superName, interfaces);
        }
    };
    reader.accept(cv, ClassReader.EXPAND_FRAMES);
    byte[] result = writer.toByteArray();
    return result;
}
Also used : InstrumentationContext(com.newrelic.agent.instrumentation.context.InstrumentationContext) ClassWeavedListener(com.newrelic.weave.weavepackage.ClassWeavedListener) PackageWeaveResult(com.newrelic.weave.weavepackage.PackageWeaveResult) Method(com.newrelic.agent.deps.org.objectweb.asm.commons.Method) ClassVisitor(com.newrelic.agent.deps.org.objectweb.asm.ClassVisitor) TraceClassVisitor(com.newrelic.agent.instrumentation.tracing.TraceClassVisitor) IOException(java.io.IOException) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter) ClassWriter(com.newrelic.agent.deps.org.objectweb.asm.ClassWriter) TraceClassVisitor(com.newrelic.agent.instrumentation.tracing.TraceClassVisitor) NoticeSqlVisitor(com.newrelic.agent.instrumentation.tracing.NoticeSqlVisitor) ScalaTraitMatcher(com.newrelic.agent.instrumentation.classmatchers.ScalaTraitMatcher) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter) ClassReader(com.newrelic.agent.deps.org.objectweb.asm.ClassReader) URLClassLoader(java.net.URLClassLoader) ClassCache(com.newrelic.weave.utils.ClassCache) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map)

Example 2 with PatchedClassWriter

use of com.newrelic.agent.util.asm.PatchedClassWriter in project newrelic-java-agent by newrelic.

the class FinalClassTransformer method getFinalTransformation.

private byte[] getFinalTransformation(ClassLoader loader, String className, Class<?> classBeingRedefined, byte[] classfileBuffer, InstrumentationContext context) {
    ClassReader reader = new ClassReader(classfileBuffer);
    ClassWriter writer = new PatchedClassWriter(ClassWriter.COMPUTE_FRAMES, context.getClassResolver(loader));
    ClassVisitor cv = writer;
    if (!context.getWeavedMethods().isEmpty()) {
        cv = new MarkWeaverMethodsVisitor(cv, context);
    }
    cv = addModifiedClassAnnotation(cv, context);
    cv = addModifiedMethodAnnotation(cv, context, loader);
    cv = new ClassVisitor(WeaveUtils.ASM_API_LEVEL, cv) {

        @Override
        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            if (version < 49 || version > 100) {
                // Some weird Apache classes have really large versions.
                int newVersion = WeaveUtils.RUNTIME_MAX_SUPPORTED_CLASS_VERSION;
                if (CLASSES_TO_SKIP_VERSION_UPGRADE.contains(name)) {
                    newVersion = WeaveUtils.JAVA_6_CLASS_VERSION;
                }
                Agent.LOG.log(Level.FINEST, "Converting {0} from version {1} to {2}", name, version, newVersion);
                version = newVersion;
            }
            super.visit(version, access, name, signature, superName, interfaces);
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions);
        }
    };
    cv = skipExistingAnnotations(cv);
    cv = CurrentTransactionRewriter.rewriteCurrentTransactionReferences(cv, reader);
    reader.accept(cv, ClassReader.SKIP_FRAMES);
    byte[] classBytes = writer.toByteArray();
    if (CLASS_CHECKER != null) {
        CLASS_CHECKER.check(classBytes);
    }
    if (Agent.isDebugEnabled()) {
        writeClassFiles(className, context, classBytes);
    }
    addSupportabilityMetrics(reader, className, context);
    Agent.LOG.finer("Final transformation of class " + className);
    return classBytes;
}
Also used : PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter) ClassReader(org.objectweb.asm.ClassReader) ClassVisitor(org.objectweb.asm.ClassVisitor) ClassWriter(org.objectweb.asm.ClassWriter) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter) JSRInlinerAdapter(org.objectweb.asm.commons.JSRInlinerAdapter) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 3 with PatchedClassWriter

use of com.newrelic.agent.util.asm.PatchedClassWriter in project newrelic-java-agent by newrelic.

the class JVMClassTransformerTest method convertToClassBytes.

/**
 * Converts an ASM {@link ClassNode} to a byte array. Us
 *
 * @param classNode class node to convert
 * @param classloader the classloader used to create the {@link PatchedClassWriter}
 * @return byte array representing the specified class node
 */
public static byte[] convertToClassBytes(ClassNode classNode, ClassLoader classloader) {
    // ClassWriter cw = new PatchedClassWriter(ClassWriter.COMPUTE_FRAMES, classloader);
    ClassWriter cw = new ClassWriter(WeaveUtils.ASM_API_LEVEL);
    classNode.accept(cw);
    return cw.toByteArray();
}
Also used : ClassWriter(org.objectweb.asm.ClassWriter) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter)

Example 4 with PatchedClassWriter

use of com.newrelic.agent.util.asm.PatchedClassWriter in project newrelic-java-agent by newrelic.

the class ExtensionRewriter method rewrite.

/**
 * Given a jar file, return the bytes for a new jar in which all classes have been modified so that references to
 * dependencies that we repackage in the agent are rewritten to reference the repackaged classes. If no such
 * references are found, a null is returned.
 *
 * @return the bytes for a new jar file, or null if no new jar is needed
 */
public static byte[] rewrite(JarFile jar, ClassLoader classLoader) throws IOException {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    JarOutputStream jarOut = new JarOutputStream(out);
    boolean modified = false;
    try {
        for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
            JarEntry entry = e.nextElement();
            JarEntry newEntry = new JarEntry(entry.getName());
            InputStream inputStream = jar.getInputStream(entry);
            try {
                if (entry.getName().endsWith(".class")) {
                    ClassReader cr = new ClassReader(inputStream);
                    ClassWriter writer = new PatchedClassWriter(ClassWriter.COMPUTE_FRAMES, classLoader);
                    ClassVisitor cv = new ClassRemapper(writer, REMAPPER);
                    cr.accept(cv, ClassReader.SKIP_FRAMES);
                    if (!REMAPPER.getRemappings().isEmpty()) {
                        modified = true;
                    }
                    inputStream.close();
                    inputStream = new ByteArrayInputStream(writer.toByteArray());
                }
                jarOut.putNextEntry(newEntry);
                Streams.copy(inputStream, jarOut, inputStream.available());
            } finally {
                jarOut.closeEntry();
                inputStream.close();
            }
        }
    } finally {
        jarOut.close();
        jar.close();
        out.close();
    }
    return modified ? out.toByteArray() : null;
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter) JarOutputStream(java.util.jar.JarOutputStream) ClassReader(org.objectweb.asm.ClassReader) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ClassVisitor(org.objectweb.asm.ClassVisitor) JarEntry(java.util.jar.JarEntry) ClassRemapper(org.objectweb.asm.commons.ClassRemapper) ClassWriter(org.objectweb.asm.ClassWriter) PatchedClassWriter(com.newrelic.agent.util.asm.PatchedClassWriter)

Aggregations

PatchedClassWriter (com.newrelic.agent.util.asm.PatchedClassWriter)4 ClassWriter (org.objectweb.asm.ClassWriter)3 ClassReader (org.objectweb.asm.ClassReader)2 ClassVisitor (org.objectweb.asm.ClassVisitor)2 ClassReader (com.newrelic.agent.deps.org.objectweb.asm.ClassReader)1 ClassVisitor (com.newrelic.agent.deps.org.objectweb.asm.ClassVisitor)1 ClassWriter (com.newrelic.agent.deps.org.objectweb.asm.ClassWriter)1 Method (com.newrelic.agent.deps.org.objectweb.asm.commons.Method)1 ScalaTraitMatcher (com.newrelic.agent.instrumentation.classmatchers.ScalaTraitMatcher)1 InstrumentationContext (com.newrelic.agent.instrumentation.context.InstrumentationContext)1 NoticeSqlVisitor (com.newrelic.agent.instrumentation.tracing.NoticeSqlVisitor)1 TraceClassVisitor (com.newrelic.agent.instrumentation.tracing.TraceClassVisitor)1 ClassCache (com.newrelic.weave.utils.ClassCache)1 ClassWeavedListener (com.newrelic.weave.weavepackage.ClassWeavedListener)1 PackageWeaveResult (com.newrelic.weave.weavepackage.PackageWeaveResult)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 URLClassLoader (java.net.URLClassLoader)1