We are using Java agent to enhance some methods in the application. The agent are dependent on other jars, and for convenience, so we packaged the agent and dependencies into a fatjar, and then load the dependent jars through a custom class loader. The program can startup normally but very slowly, and it takes a few minutes to startup completely. (I counted the loading time of each class (loadclass()in ClassLoader ) and found that the loading of some classes takes hundreds of milliseconds). Similarly, when I used spring boot (also fatjar with same dependencies), it would be much faster.
The version of JDK is 1.8.0_261.
The premain method is as follows:
public static void premain(String args, Instrumentation instrumentation) throws Exception {
final AgentLanucher agentLauncher = new AgentLanucher(); //----1
agentLauncher.launch(); //----2
// add transformer
instrumentation.addTransformer(new CustomAgentTransformer);
}
And the code of AgentLauncher is as follows:
import org.springframework.boot.loader.JarLauncher;
public class AgentLanucher extends JarLauncher {
@Override
protected void launch(String[] args) throws Exception{
super.launch(args);
}
}
When executing the code marked with (1,2), loading one class takes a long time (tens or hundreds of milliseconds). The code for counting time of loading one class is as follows:
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
final long start = System.currentTimeMillis();
final Class<?> clazz = super.loadClass(name, resolve);
final long end = System.currentTimeMillis();
System.out.println("Load [" + name + "] : " + (end -start));
return clazz;
}
And I found that When the program run with JDK11, it run quickly. Then I changed the version back to JDK8, but moved the codes from the premain to a separate thread, it run quickly too. The codes is as follows:
public static void premain(String args, Instrumentation instrumentation) {
CompletableFuture.runAsync(()->{
final AgentLauncher launcher = new AgentLauncher();
launcher.launch();
instrumentation.addTransformer(new CustomAgentTransformer());
});
}
There is another attempt, I blocked the main thread until the sub-thread completed. It run slowly. The codes is as follows:
public static void premain(String args, Instrumentation instrumentation) {
final CompletableFuture<Void> initTask = CompletableFuture.runAsync(() -> {
final AgentLauncher launcher = new AgentLauncher();
launcher.launch();
instrumentation.addTransformer(new CustomAgentTransformer());
});
System.out.println("Waiting.....");
initTask.join();
}
I am confused about the issue, Thanks for any help.