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;
}
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();
}
}
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);
}
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;
}
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);
}
Aggregations