public byte[] transform( ClassLoader loader, String classname, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { boolean someoneTouchedTheBytecode = false; TransformerInfo[] transformerList = getSnapshotTransformerList(); byte[] bufferToUse = classfileBuffer; // order matters, gotta run 'em in the order they were added for (int x = 0; x < transformerList.length; x++) { TransformerInfo transformerInfo = transformerList[x]; ClassFileTransformer transformer = transformerInfo.transformer(); byte[] transformedBytes = null; try { transformedBytes = transformer.transform( loader, classname, classBeingRedefined, protectionDomain, bufferToUse); } catch (Throwable t) { // don't let any one transformer mess it up for the others. // This is where we need to put some logging. What should go here? FIXME } if (transformedBytes != null) { someoneTouchedTheBytecode = true; bufferToUse = transformedBytes; } } // if someone modified it, return the modified buffer. // otherwise return null to mean "no transforms occurred" byte[] result; if (someoneTouchedTheBytecode) { result = bufferToUse; } else { result = null; } return result; }
/* * ClassFileLoadHook event handler method */ private byte[] transform( ClassLoader loader, byte[] classNameBytes, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { byte[] source = classfileBuffer; byte[] result = null; byte[] trans = null; String className = new String(classNameBytes); for (ClassFileTransformer t : transformers) { try { trans = t.transform(loader, className, classBeingRedefined, protectionDomain, source); if (null != trans && 0 != trans.length) { result = trans; source = trans; } } catch (Exception e) { // nothing to do, just continue~ } } return result; }
@Override public void onLoad(ClassPool pool, String classname) throws NotFoundException, CannotCompileException { logger.debug("loading className:{}", classname); try { // Find Modifier from agent and try transforming String replace = classname.replace('.', '/'); ClassFileTransformer classFileTransformer = agent.getClassFileTransformer(); byte[] transform = classFileTransformer.transform(this.loader, replace, null, null, null); if (transform != null) { pool.makeClass(new ByteArrayInputStream(transform)); return; } } catch (IOException ex) { throw new NotFoundException(classname + " not found. Caused:" + ex.getMessage(), ex); } catch (IllegalClassFormatException ex) { throw new RuntimeException(classname + " not found. Caused:" + ex.getMessage(), ex); } // find from modifierMap findModifierMap(pool, classname); }
@Override public byte[] transform( ClassLoader loader, String className, Class<?> redefinedClass, ProtectionDomain protectionDomain, byte[] bytecode) throws IllegalClassFormatException { byte[] data = transformer.transform(loader, className, redefinedClass, protectionDomain, bytecode); if (data != null) { DebugUtils.dump(className, data, Kind.CLASS); } return data; }