Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在不活动后调用java.beans.Introspector.getBeanInfo时出现性能问题_Java_Performance_Reflection_Blazeds_Javabeans - Fatal编程技术网

在不活动后调用java.beans.Introspector.getBeanInfo时出现性能问题

在不活动后调用java.beans.Introspector.getBeanInfo时出现性能问题,java,performance,reflection,blazeds,javabeans,Java,Performance,Reflection,Blazeds,Javabeans,我正在使用一个第三方库,它可以动态创建Java类的实例,并在Introspector.getBeanInfo的帮助下填充这些实例。某些请求可能会导致连续调用Introspector.getBeanInfo。我发现,当应用程序空闲大约一个小时时,第一次调用Introspector.getBeanInfo所需的执行时间(20-60秒)要比后续调用(

我正在使用一个第三方库,它可以动态创建Java类的实例,并在
Introspector.getBeanInfo
的帮助下填充这些实例。某些请求可能会导致连续调用
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));
我最初认为这个问题可能与这样一个事实有关,即内省类试图根据我的应用程序中不存在的标准命名约定(例如,
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类,以便准确指出延迟的确切位置(这是对
flex.messaging.io.BeanProxy
getPropertyDescriptorCacheEntry
方法中的
Introspector.getBeanInfo
的调用)。此外,BlazeDS确实缓存BeanInfo,因此只有当Blaze对映射到尚未处理的Java类的对象进行反序列化时,才会调用
Introspector.getBeanInfo
。因此,我确实有其他方法来解决此问题,但我真的很想知道这种行为是否有有效的解释

编辑: 我在复制问题的同时多次在进程上运行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)
    - locked <0x1803dd38> (a org.apache.catalina.loader.WebappClassLoader)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1517)
    at java.beans.Introspector.instantiate(Unknown Source)
    at java.beans.Introspector.findExplicitBeanInfo(Unknown Source)
    - locked <0x434649a0> (a java.lang.Class for java.beans.Introspector)
    at java.beans.Introspector.<init>(Unknown Source)
    at java.beans.Introspector.getBeanInfo(Unknown Source)
    - locked <0x181bed70> (a java.lang.Object)
“http-8080-exec-6”守护程序prio=6 tid=0x65cae800 nid=0x1a50可运行[0x67a3d000]
java.lang.Thread.State:可运行
位于java.util.zip.ZipFile.open(本机方法)
位于java.util.zip.ZipFile。(未知源)
位于java.util.jar.JarFile。(未知源)
位于java.util.jar.JarFile。(未知源)
位于org.apache.catalina.loader.WebappClassLoader.openJARs(WebappClassLoader.java:2704)
位于org.apache.catalina.loader.WebappClassLoader.findResourceInternal(WebappClassLoader.java:2945)
-锁定(一个[Ljava.util.jar.JarFile;)
位于org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2739)
位于org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1144)
位于org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1639)
-锁定(org.apache.catalina.loader.WebappClassLoader)
位于org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1517)
位于java.beans.Introspector.instantiate(未知源)
位于java.beans.Introspector.findExplicitBeanInfo(未知源)
-锁定(java.beans.Introspector的java.lang.Class)
位于java.beans.Introspector。(未知源)
位于java.beans.Introspector.getBeanInfo(未知源代码)
-锁定(一个java.lang.Object)
我忍不住认为有某种JRE/JVM jar缓存在一小时后过期,并强制重新扫描jar文件,但我在网上找不到任何描述这种行为的东西

编辑: 事实证明,Tomcat
WebappClassLoader
缓存JAR文件并定期清除该缓存

编辑:
Tomcat在上一次访问JAR文件90秒后关闭所有JAR文件。我重写了
WebappClassLoader
,以便在JAR文件关闭时打印出来。JAR文件关闭后,我试图重现延迟,但无法执行。因此,这告诉我JRE/JVM JAR文件缓存或者只是其中的某个内容租入操作系统(或我的机器、防病毒软件等),在长时间延迟后导致加载时间变慢。仍在处理它…

在我的雇主,我们也严重依赖动态生成的类。由于
内省器的问题以及它的行为(例如依赖类加载器行为)尝试加载许多我们没有的
*BeanInfo
类,这对我们来说是不可能的,我们决定不使用内省和重新实现我们自己的功能

不确定您真正需要多少BeanInfo,但使用反射和自制的属性元数据信息组件可能更容易,您可以更好地控制这些组件。使用更容易,我还指的是,一旦您将应用部署到其他应用程序服务器上,您就可以放心了,这些应用程序服务器都有自己的类
private static boolean cacheJarFiles = true;
public void closeJARs(boolean force) {
   if (cacheJarFiles) {
      return;
   }
   if (jarFiles.length > 0) {
      synchronized (jarFiles) {
         if (force || (System.currentTimeMillis() 
}