Search in sources :

Example 1 with ClassCache

use of com.newrelic.weave.utils.ClassCache 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 ClassCache

use of com.newrelic.weave.utils.ClassCache in project newrelic-java-agent by newrelic.

the class WeavePackageManager method validateAgainstClassLoader.

/**
 * Determine if the weavePackage is valid against classloader (using cache to check for resources).
 */
private boolean validateAgainstClassLoader(String className, String superName, String[] interfaceNames, ClassLoader classloader, ClassCache cache, WeavePackage weavePackage) throws IOException {
    if (classloader != BootstrapLoader.PLACEHOLDER && weavePackage.weavesBootstrap()) {
        classloader = BootstrapLoader.PLACEHOLDER;
        cache = new ClassCache(BootstrapLoader.get());
    }
    try {
        // this is the first time we've validated this package against this classloader.
        if (!hasValidated(classloader, weavePackage)) {
            PackageValidationResult verificationResult = weavePackage.validate(cache);
            currentValidationResult.set(verificationResult);
            if (null != packageListener) {
                packageListener.validated(verificationResult, classloader);
            }
            if ((classloader == BootstrapLoader.PLACEHOLDER && !this.canWeaveBootstrapClassLoader()) || (!verificationResult.succeeded())) {
                ConcurrentMap<WeavePackage, PackageValidationResult> result = invalidPackages.asMap().putIfAbsent(classloader, new ConcurrentHashMap<WeavePackage, PackageValidationResult>());
                if (result == null) {
                    result = invalidPackages.asMap().get(classloader);
                }
                result.put(weavePackage, verificationResult);
                return false;
            } else {
                // We need to add this to the valid packages list before appending new classes to prevent a circular class load
                ConcurrentMap<WeavePackage, PackageValidationResult> result = validPackages.asMap().putIfAbsent(classloader, new ConcurrentHashMap<WeavePackage, PackageValidationResult>());
                if (result == null) {
                    result = validPackages.asMap().get(classloader);
                }
                try {
                    if (BootstrapLoader.PLACEHOLDER == classloader) {
                        NewClassAppender.appendClassesToBootstrapClassLoader(instrumentation, verificationResult.computeUtilityClassBytes(cache));
                    } else {
                        NewClassAppender.appendClasses(className, superName, interfaceNames, classloader, verificationResult.computeUtilityClassBytes(cache));
                    }
                    result.put(weavePackage, verificationResult);
                } catch (Throwable t) {
                    // If the new class appending above throws an exception we need to remove the validated package (since it's no longer valid)
                    result.remove(weavePackage);
                }
            }
        }
        ConcurrentMap<WeavePackage, PackageValidationResult> result = validPackages.getIfPresent(classloader);
        return result != null && result.containsKey(weavePackage);
    } finally {
        currentValidationResult.remove();
    }
}
Also used : ClassCache(com.newrelic.weave.utils.ClassCache)

Example 3 with ClassCache

use of com.newrelic.weave.utils.ClassCache in project newrelic-java-agent by newrelic.

the class WeavePackageManager method weave.

/**
 * Weave all of the matched packages with the specified target bytes and return the composite class.
 *
 * @param classloader classloader to resolve classes with
 * @param className target class name
 * @param targetBytes target class bytes
 * @return composite class bytes, or <code>null</code> if no weaving occurred
 */
public byte[] weave(ClassLoader classloader, String className, byte[] targetBytes, Map<Method, Collection<String>> skipMethods) throws IOException {
    classloader = classLoaderSub(classloader);
    ClassCache cache = new ClassCache(new ClassLoaderFinder(classloader));
    return weave(classloader, cache, className, targetBytes, skipMethods, null);
}
Also used : ClassLoaderFinder(com.newrelic.weave.utils.ClassLoaderFinder) ClassCache(com.newrelic.weave.utils.ClassCache)

Example 4 with ClassCache

use of com.newrelic.weave.utils.ClassCache in project newrelic-java-agent by newrelic.

the class WeaveTestUtils method weaveAndAddToContextClassloader.

/**
 * Weaves the original class with the weave class, adds the result to the system classloader.
 *
 * @param originalName original Java classname, e.g. "java.lang.Object"
 * @param weaveName weave Java classname, e.g. "java.lang.Object"
 * @param targetName target Java classname, e.g. "java.lang.Object"
 * @param errorHandlerClassNode a class node of an {@link ErrorTrapHandler} class.
 * @throws IOException
 */
public static ClassWeave weaveAndAddToContextClassloader(String originalName, String weaveName, String targetName, boolean isBaseMatch, Set<String> requiredClassAnnotations, Set<String> requiredMethodAnnotations, ClassNode errorHandlerClassNode, ClassNode extensionTemplate) throws IOException {
    ClassNode originalClass = readClass(originalName);
    ClassNode weaveClass = readClass(weaveName);
    ClassNode target = originalName.equals(targetName) ? originalClass : readClass(targetName);
    ClassCache contextCache = createContextCache();
    ClassWeave weave = weave(originalClass, weaveClass, target, isBaseMatch, requiredClassAnnotations, requiredMethodAnnotations, errorHandlerClassNode, extensionTemplate, contextCache);
    addToContextClassloader(weave, contextCache);
    return weave;
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) ClassCache(com.newrelic.weave.utils.ClassCache)

Example 5 with ClassCache

use of com.newrelic.weave.utils.ClassCache in project newrelic-java-agent by newrelic.

the class WeaveTestUtils method expectViolations.

/**
 * Validate the WeavePackage against a ClassLoader and assert that exactly the expected violations occur.
 *
 * @param weavePackage package to validate
 * @param classloader classloader to validate against
 * @param expected exepcted violations
 * @throws IOException
 */
public static void expectViolations(WeavePackage weavePackage, ClassLoader classloader, WeaveViolation... expected) throws IOException {
    List<WeaveViolation> actual = weavePackage.validate(new ClassCache(new ClassLoaderFinder(classloader))).getViolations();
    expectViolations(actual, expected);
}
Also used : ClassLoaderFinder(com.newrelic.weave.utils.ClassLoaderFinder) WeaveViolation(com.newrelic.weave.violation.WeaveViolation) ClassCache(com.newrelic.weave.utils.ClassCache)

Aggregations

ClassCache (com.newrelic.weave.utils.ClassCache)26 ClassLoaderFinder (com.newrelic.weave.utils.ClassLoaderFinder)20 Test (org.junit.Test)12 ArrayList (java.util.ArrayList)6 IOException (java.io.IOException)5 ClassNode (org.objectweb.asm.tree.ClassNode)5 WeaveViolation (com.newrelic.weave.violation.WeaveViolation)4 PackageValidationResult (com.newrelic.weave.weavepackage.PackageValidationResult)4 PackageWeaveResult (com.newrelic.weave.weavepackage.PackageWeaveResult)3 WeavePackage (com.newrelic.weave.weavepackage.WeavePackage)3 MyOriginalExact (com.newrelic.weave.weavepackage.testclasses.MyOriginalExact)3 ClassInformation (com.newrelic.weave.utils.ClassInformation)2 ClassWeavedListener (com.newrelic.weave.weavepackage.ClassWeavedListener)2 MyOriginalTarget1 (com.newrelic.weave.weavepackage.testclasses.MyOriginalTarget1)2 WeaveUtilityClass (com.newrelic.weave.weavepackage.testclasses.WeaveUtilityClass)2 ExecutorService (java.util.concurrent.ExecutorService)2 Future (java.util.concurrent.Future)2 Method (org.objectweb.asm.commons.Method)2 ClassReader (com.newrelic.agent.deps.org.objectweb.asm.ClassReader)1 ClassVisitor (com.newrelic.agent.deps.org.objectweb.asm.ClassVisitor)1