Search in sources :

Example 1 with ClassInformation

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

the class Reference method addMethodsAndFields.

/**
 * Fetch all methods and fields of a class node including those inherited from supertypes+interfaces. The results
 * will be stored in the passed in methods and fields lists.
 *
 * @param classCache Cache to use to fetch supertype resources
 * @param classNode The node to scan
 * @param methods classNode's methods will be appended to this list.
 * @param fields classNode's fields will be appended to this list.
 */
private static void addMethodsAndFields(ClassCache classCache, ClassNode classNode, List<MethodNode> methods, List<FieldNode> fields) throws IOException {
    ClassInformation classInfo = classCache.getClassInformation(classNode.name);
    for (MemberInformation methodInfo : classInfo.getAllMethods(classCache)) {
        MethodNode methodNode = new SynchronizedMethodNode();
        methodNode.name = methodInfo.name;
        methodNode.desc = methodInfo.desc;
        methodNode.access = methodInfo.access;
        methods.add(methodNode);
    }
    for (MemberInformation fieldInfo : classInfo.getAllFields(classCache)) {
        fields.add(new SynchronizedFieldNode(WeaveUtils.ASM_API_LEVEL, fieldInfo.access, fieldInfo.name, fieldInfo.desc, null, null));
    }
}
Also used : ClassInformation(com.newrelic.weave.utils.ClassInformation) MethodNode(org.objectweb.asm.tree.MethodNode) SynchronizedMethodNode(com.newrelic.weave.utils.SynchronizedMethodNode) SynchronizedMethodNode(com.newrelic.weave.utils.SynchronizedMethodNode) MemberInformation(com.newrelic.weave.utils.ClassInformation.MemberInformation) SynchronizedFieldNode(com.newrelic.weave.utils.SynchronizedFieldNode)

Example 2 with ClassInformation

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

the class WeavePackage method hasMatcher.

/**
 * Returns true if this package contains at least one matcher for a class.
 */
public boolean hasMatcher(String className, String[] superNames, String[] interfaceNames, Set<String> classAnnotations, Set<String> methodAnnotations, ClassCache classCache) throws IOException {
    if (this.exactWeaves.containsKey(className) || this.baseWeaves.containsKey(className))
        return true;
    for (int i = 0; i < superNames.length; ++i) {
        if (this.baseWeaves.containsKey(superNames[i]))
            return true;
    }
    for (int i = 0; i < interfaceNames.length; ++i) {
        if (this.baseWeaves.containsKey(interfaceNames[i]))
            return true;
    }
    // Check to see if any of the annotations on the class exist in the set of required Exact match annotations
    Set<String> matchingAnnotations = Sets.intersection(allClassAnnotationWeaves.keySet(), classAnnotations);
    if (!matchingAnnotations.isEmpty()) {
        return true;
    }
    // If we have any base/interface annotation weaves check to see if the interfaces have the correct annotation(s)
    if (!baseAnnotationWeaves.isEmpty()) {
        Set<String> requiredBaseAnnotations = baseAnnotationWeaves.keySet();
        for (String interfaceName : interfaceNames) {
            ClassInformation classInformation = classCache.getClassInformation(interfaceName);
            if (classHasRequiredAnnotations(classInformation, requiredBaseAnnotations)) {
                return true;
            }
        }
    }
    // Check to see if any of the annotations on the methods exist in the set of required method annotations
    Set<String> matchingMethodAnnotations = Sets.intersection(allMethodAnnotationWeaves.keySet(), methodAnnotations);
    if (!matchingMethodAnnotations.isEmpty()) {
        return true;
    }
    return false;
}
Also used : ClassInformation(com.newrelic.weave.utils.ClassInformation)

Example 3 with ClassInformation

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

the class WeavePackageManager method weave.

/**
 * Weave all of the matched packages with the specified target bytes using the specified cache and listener.
 *
 * @param classloader classloader to resolve classes with
 * @param cache {@link ClassCache} to find class metadata
 * @param className target class name
 * @param targetBytes target class bytes
 * @param weaveListener listener containing callback if/when the composite is created
 * @return composite class bytes, or <code>null</code> if no weaving occurred
 */
public byte[] weave(ClassLoader classloader, ClassCache cache, String className, byte[] targetBytes, Map<Method, Collection<String>> skipMethods, ClassWeavedListener weaveListener) throws IOException {
    classloader = classLoaderSub(classloader);
    if (preMatchWeaveMethods && !containsPossibleClassOrMethodMatch(className, targetBytes, requiredClasses, methodSignatures, cache)) {
        // No potential method match was found, we are definitely not weaving this class so we should exit now
        return null;
    }
    ClassInformation classInformation = cache.getClassInformation(className);
    if (classInformation == null) {
        return null;
    }
    String[] superNames = cache.getClassInformation(className).getAllSuperNames(cache).toArray(new String[0]);
    String[] interfaceNames = cache.getClassInformation(className).getAllInterfaces(cache).toArray(new String[0]);
    Set<String> classAnnotations = cache.getClassInformation(className).classAnnotationNames;
    Set<String> methodAnnotations = cache.getClassInformation(className).methodAnnotationNames;
    Set<PackageValidationResult> matchedPackageResults = this.match(classloader, cache, className, classAnnotations, methodAnnotations, superNames, interfaceNames);
    if (matchedPackageResults.isEmpty()) {
        return null;
    }
    ClassNode composite = WeaveUtils.convertToClassNode(targetBytes);
    PackageWeaveResult finalResult = null;
    for (PackageValidationResult weavePackageResult : matchedPackageResults) {
        PackageWeaveResult result = weavePackageResult.weave(className, superNames, interfaceNames, composite, cache, skipMethods);
        if (null != weaveListener) {
            weaveListener.classWeaved(result, classloader, cache);
        }
        if (result.weavedClass()) {
            composite = result.getComposite();
            finalResult = result;
        }
    }
    return null == finalResult ? null : finalResult.getCompositeBytes(cache);
}
Also used : ClassNode(org.objectweb.asm.tree.ClassNode) ClassInformation(com.newrelic.weave.utils.ClassInformation)

Example 4 with ClassInformation

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

the class ClassWeaverService method transform.

@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer, final InstrumentationContext context, Match match) throws IllegalClassFormatException {
    if (!PointCutClassTransformer.isValidClassName(className)) {
        return null;
    }
    ClassWeavedListener classWeavedCallback = new ClassWeavedListener() {

        @Override
        public void classWeaved(PackageWeaveResult weaveResult, ClassLoader classloader, ClassCache cache) {
            List<WeaveViolation> violations = weaveResult.getValidationResult().getViolations();
            if (!violations.isEmpty()) {
                // This is due to the nature of annotation weaving happening at weave time instead of validation time
                weaveViolationLogger.logWeaveViolations(weaveResult.getValidationResult(), classloader, false);
                return;
            }
            final String packageName = weaveResult.getValidationResult().getWeavePackage().getName();
            if (Agent.LOG.isFinerEnabled()) {
                try {
                    if (Agent.LOG.isFinerEnabled()) {
                        ClassInformation weavedClass = cache.getClassInformation(weaveResult.getClassName());
                        Agent.LOG.log(Level.FINER, "{0} matched {1}", packageName, weavedClass.className);
                        for (String superName : weavedClass.getAllSuperNames(cache)) {
                            Agent.LOG.log(Level.FINER, "\ts: {0}", superName);
                        }
                        for (String interfaceName : weavedClass.getAllInterfaces(cache)) {
                            Agent.LOG.log(Level.FINER, "\ti: {0}", interfaceName);
                        }
                    }
                } catch (IOException ioe) {
                    Agent.LOG.log(Level.FINEST, ioe, "exception while getting supertype info");
                }
            }
            if (weaveResult.weavedClass()) {
                try {
                    Map<String, byte[]> annotationProxyClasses = weaveResult.getAnnotationProxyClasses();
                    if (!annotationProxyClasses.isEmpty()) {
                        // the dynamic proxy classes that we created to the current classloader at this point
                        if (BootstrapLoader.PLACEHOLDER == classloader) {
                            NewClassAppender.appendClassesToBootstrapClassLoader(instrumentation, annotationProxyClasses);
                        } else {
                            NewClassAppender.appendClasses(classloader, annotationProxyClasses);
                        }
                    }
                } catch (Exception e) {
                    Agent.LOG.log(Level.FINE, e, "Unable to add annotation proxy classes");
                }
                String weaveClassStat = MessageFormat.format(MetricNames.SUPPORTABILITY_WEAVE_CLASS, packageName, weaveResult.getClassName());
                ServiceFactory.getStatsService().doStatsWork(StatsWorks.getRecordMetricWork(weaveClassStat, 1), weaveClassStat);
                for (String originalName : weaveResult.getWeavedMethods().keySet()) {
                    Agent.LOG.log(Level.FINE, "{0}: weaved target {1}-{2}", packageName, classloader, weaveResult.getClassName());
                    for (Method method : weaveResult.getWeavedMethods().get(originalName)) {
                        Agent.LOG.log(Level.FINE, "\t{0}.{1}:{2}", originalName, method.getName(), method.getDescriptor());
                        context.addWeavedMethod(method, packageName);
                    }
                    addTraceInformation(ClassWeaverService.this.tracedWeaveInstrumentationDetails, packageName, context, weaveResult.getComposite(), originalName);
                }
            } else {
                Agent.LOG.log(Level.FINER, "{0} matched class {1} but no methods were weaved.", packageName, weaveResult.getClassName());
            }
        }
    };
    try {
        return weavePackageManager.weave(loader, getClassCache(loader), className, classfileBuffer, context.getSkipMethods(), classWeavedCallback);
    } catch (IOException ioe) {
        throw new RuntimeException(ioe);
    }
}
Also used : ClassWeavedListener(com.newrelic.weave.weavepackage.ClassWeavedListener) ClassInformation(com.newrelic.weave.utils.ClassInformation) PackageWeaveResult(com.newrelic.weave.weavepackage.PackageWeaveResult) WeaveViolation(com.newrelic.weave.violation.WeaveViolation) IOException(java.io.IOException) Method(org.objectweb.asm.commons.Method) IllegalClassFormatException(java.lang.instrument.IllegalClassFormatException) IOException(java.io.IOException) ClassCache(com.newrelic.weave.utils.ClassCache)

Example 5 with ClassInformation

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

the class ClassMatch method requiredMethodAnnotationInInterface.

private boolean requiredMethodAnnotationInInterface(MethodNode originalMethod, Set<String> methodRequiredAnnotations, ClassCache cache) {
    try {
        for (String interfaceName : original.interfaces) {
            ClassInformation interfaceInformation = cache.getClassInformation(interfaceName);
            for (ClassInformation.MemberInformation method : interfaceInformation.methods) {
                if (method.name.equals(originalMethod.name) && method.desc.equals(originalMethod.desc)) {
                    Set<AnnotationNode> annotations = method.annotations;
                    Set<String> annotationClasses = new HashSet<>();
                    for (AnnotationNode annotation : annotations) {
                        annotationClasses.add(Type.getType(annotation.desc).getClassName());
                    }
                    if (WeaveUtils.hasRequiredAnnotations(annotationClasses, methodRequiredAnnotations)) {
                        return true;
                    }
                }
            }
        }
    } catch (IOException ignored) {
    }
    return false;
}
Also used : ClassInformation(com.newrelic.weave.utils.ClassInformation) AnnotationNode(org.objectweb.asm.tree.AnnotationNode) IOException(java.io.IOException) HashSet(java.util.HashSet)

Aggregations

ClassInformation (com.newrelic.weave.utils.ClassInformation)11 IOException (java.io.IOException)5 AnnotationNode (org.objectweb.asm.tree.AnnotationNode)3 ClassCache (com.newrelic.weave.utils.ClassCache)2 HashSet (java.util.HashSet)2 Method (org.objectweb.asm.commons.Method)2 MethodNode (org.objectweb.asm.tree.MethodNode)2 MemberInformation (com.newrelic.weave.utils.ClassInformation.MemberInformation)1 ClassLoaderFinder (com.newrelic.weave.utils.ClassLoaderFinder)1 SynchronizedFieldNode (com.newrelic.weave.utils.SynchronizedFieldNode)1 SynchronizedMethodNode (com.newrelic.weave.utils.SynchronizedMethodNode)1 WeaveViolation (com.newrelic.weave.violation.WeaveViolation)1 ClassWeavedListener (com.newrelic.weave.weavepackage.ClassWeavedListener)1 PackageWeaveResult (com.newrelic.weave.weavepackage.PackageWeaveResult)1 IllegalClassFormatException (java.lang.instrument.IllegalClassFormatException)1 Instrumentation (java.lang.instrument.Instrumentation)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 Test (org.junit.Test)1