Skip to content

Instantly share code, notes, and snippets.

@wu-sheng
Last active March 7, 2024 06:14
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wu-sheng/101667979034e019c451ebb7e481d9a6 to your computer and use it in GitHub Desktop.
Save wu-sheng/101667979034e019c451ebb7e481d9a6 to your computer and use it in GitHub Desktop.
byte-buddy appendToBootstrapClassLoaderSearch, and jdk instrumentation
/**
* All codes from stagemonitor apm, which gives a example about how to use instrumentation::appendToBootstrapClassLoaderSearch
* This will be very useful for instrument some class in rt.jar
*/
private static boolean initInstrumentation() {
try {
/**
* this try-catch block shows two ways about instrumentation.
* ref issue: https://github.com/raphw/byte-buddy/issues/237
*/
try {
instrumentation = ByteBuddyAgent.getInstrumentation();
} catch (IllegalStateException e) {
instrumentation = ByteBuddyAgent.install(
new ByteBuddyAgent.AttachmentProvider.Compound(
new EhCacheAttachmentProvider(),
ByteBuddyAgent.AttachmentProvider.DEFAULT));
}
ensureDispatcherIsAppendedToBootstrapClasspath(instrumentation);
if (!Dispatcher.getValues().containsKey(IGNORED_CLASSLOADERS_KEY)) {
Dispatcher.put(IGNORED_CLASSLOADERS_KEY, Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>()));
}
hashCodesOfClassLoadersToIgnore = Dispatcher.get(IGNORED_CLASSLOADERS_KEY);
return true;
} catch (Exception e) {
logger.warn("Failed to perform runtime attachment of the stagemonitor agent. Make sure that you run your " +
"application with a JDK (not a JRE)." +
"To make stagemonitor work with a JRE, you have to add the following command line argument to the " +
"start of the JVM: -javaagent:/path/to/byte-buddy-agent-<version>.jar", e);
return false;
}
}
private static void ensureDispatcherIsAppendedToBootstrapClasspath(Instrumentation instrumentation)
throws ClassNotFoundException, IOException {
final ClassLoader bootstrapClassloader = ClassLoader.getSystemClassLoader().getParent();
try {
bootstrapClassloader.loadClass(DISPATCHER_CLASS_NAME);
// already injected
} catch (ClassNotFoundException e) {
final JarFile jarfile = new JarFile(createTempDispatcherJar());
instrumentation.appendToBootstrapClassLoaderSearch(jarfile);
bootstrapClassloader.loadClass(DISPATCHER_CLASS_NAME);
}
}
private static File createTempDispatcherJar() throws IOException {
final InputStream input = AgentAttacher.class.getClassLoader()
.getResourceAsStream("stagemonitor-dispatcher.jar.gradlePleaseDontExtract");
if (input == null) {
throw new IllegalStateException("If you see this exception inside you IDE, you have to execute gradle " +
"processResources before running the tests.");
}
final File tempDispatcherJar = File.createTempFile("stagemonitor-dispatcher", ".jar");
tempDispatcherJar.deleteOnExit();
IOUtils.copy(input, new FileOutputStream(tempDispatcherJar));
return tempDispatcherJar;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment