我正在使用第三方库,它动态创建Java类的实例并在帮助下填充这些实例Introspector.getBeanInfo.某些请求可能会导致5或6次连续呼叫Introspector.getBeanInfo.我发现当应用程序空闲大约一个小时左右时,第一次调用Introspector.getBeanInfo执行时间(20-60秒)比后续调用(<100毫秒)要长得多.在接下来的几分钟内进行的呼叫继续花费<100毫秒,但是当我再等一小时时,第一次呼叫需要20-60秒.
为了尝试使用简单的测试应用程序重新创建行为,当java应用程序本身未运行一小时时,我发现了类似的行为.例如,如果我运行以下控制台应用程序,则可能需要15毫秒才能完成.如果我再等一个小时重新运行应用程序,则需要20秒才能完成.
long start = System.currentTimeMillis();
System.out.println("Start");
Introspector.getBeanInfo(MyClass.class, Object.class);
long end = System.currentTimeMillis();
System.out.println("End: " + (end-start));
Run Code Online (Sandbox Code Playgroud)
我原本以为这个问题可能与Introspector类试图根据我的应用程序中不存在的标准命名约定创建类的实例这一事实有关(例如MyClassBeanInfo),并且扫描jar需要很长时间尝试查找这些类的文件(我的java应用程序有100多个引用的jar文件),但我Introspector.getBeanInfo(MyClass.class, Object.class, Introspector.IGNORE_ALL_BEANINFO)使用反射调用(它是Sun的JRE中的一个私有方法,从查看代码似乎跳过了BeanInfo的查找课程),我仍然能够重现延迟.
我还搜索了有关任何类型的JRE/JVM jar缓存的信息,但还没有找到任何似乎可以解释这种行为的东西.任何人都有任何线索为什么这样做会如此,如果有什么我可以做的来解决它?
作为旁注,我在Windows XP上使用JDK 1.6.0_21.我使用的第三方库是BlazeDS.我的应用程序使用Spring/BlazeDS集成托管在Tomcat中.我为了精确地查明延迟是其中(这是调用改写一些BlazeDS的类Introspector.getBeanInfo中getPropertyDescriptorCacheEntry的方法flex.messaging.io.BeanProxy).此外,BlazeDS会缓存BeanInfo,因此Introspector.getBeanInfo只有在Blaze对映射到尚未处理的Java类的对象进行反序列化时才会进行调用.所以,我确实有其他方法可以解决这个问题,但我真的想知道这种行为是否有一个有效的解释.
编辑:我在重现问题时多次运行jstack进程(感谢@Tom)并确认它与加载jar文件有关.我在20秒的时间范围内延迟了5次线程(延迟的总时间),每次产生以下结果:
"http-8080-exec-6" daemon prio=6 tid=0x65cae800 nid=0x1a50 runnable [0x67a3d000]
java.lang.Thread.State: RUNNABLE
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(Unknown Source)
at java.util.jar.JarFile.<init>(Unknown Source)
at java.util.jar.JarFile.<init>(Unknown Source)
at org.apache.catalina.loader.WebappClassLoader.openJARs(WebappClassLoader.java:2704)
at org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:2945)
- locked <0x1804cc18> (a [Ljava.util.jar.JarFile;)
at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2739)
at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1144)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1639) …Run Code Online (Sandbox Code Playgroud)