Apache POI 4.0.1超级慢入​​门... 15分钟或更长时间。怎么了? [英] Apache POI 4.0.1 super slow getting started ... 15 minutes or more. What is wrong?

查看:179
本文介绍了Apache POI 4.0.1超级慢入​​门... 15分钟或更长时间。怎么了?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

POI需要15分钟或更长时间才能在Tomcat 8实例中的Windows 10上的Java 8中初始化其第一个工作簿。基于在调试器中中断进程并查看堆栈,它在xbeans驱动的类加载器上花费了时间。



编辑
这有一个类加载器问题的感觉,因为当我实现POI库的解决方法(如下)时,其他类开始表达相同的问题。



编辑
堆栈跟踪与该错误最为相似:



我有一个解决方法,但是没有必要。接受的答案将解释为什么会这样。



编辑:解决方法



在应用程序初始化期间,我将此行添加到配置bean的静态类初始化程序中,以强制类加载器预加载类和资源。

  XSSFWorkbook preload = new XSSFWorkbook();它立即在该位置执行,并在实际流程被调用时立即执行。 

最后的解决方法是预加载与SSL,安全性和POI相关的所有jar文件。据我所知,当在春季批处理上下文中后期加载(可能是红色鲱鱼)时,类加载器正尝试使用bouncycastle类中编码的算法来验证bouncycastle jar文件,并在SSL堆栈中运行所有内容。

 反射反射=新Reflections( org.bouncycastle,this.getClass()。getClassLoader(),new SubTypesScanner(false)); 
Set< Class< ;?扩展Object>> bouncyCastleClasses = Reflections.getSubTypesOf(Object.class);



反射=新反射( sun.security,this.getClass()。getClassLoader(),new SubTypesScanner(false));
Set< Class< ;?扩展Object>> sunSecurityClasses = Reflections.getSubTypesOf(Object.class);

Reflections = new Reflections( javax.ssl,this.getClass()。getClassLoader(),new SubTypesScanner(false));
Set< Class< ;?扩展Object>> javaSslClasses = Reflections.getSubTypesOf(Object.class);

Reflections = new Reflections( org.apache.poi,this.getClass()。getClassLoader(),new SubTypesScanner(false));
Set< Class< ;?扩展Object>> poiClasses = Reflections.getSubTypesOf(Object.class);

POM摘录:

 < poi.version> 4.0.1< /poi.version> 

< ;!-apache poi / poi-ooxml->
< dependency>
< groupId> org.apache.poi< / groupId>
< artifactId> poi< / artifactId>
< version> $ {poi.version}< / version>
< / dependency>
< dependency>
< groupId> org.apache.poi< / groupId>
< artifactId> poi-scratchpad< / artifactId>
< version> $ {poi.version}< / version>
< / dependency>
< dependency>
< groupId> org.apache.poi< / groupId>
< artifactId> poi-ooxml< / artifactId>
< version> $ {poi.version}< / version>
< / dependency>

代码:

  public void beforeJob(JobExecution jobExecution){
if(logger.isDebugEnabled()){
workbookname = debuginfo- + System.currentTimeMillis()+ .xlsx;
logger.debug(调试统计信息转储文件将保存在[{}],工作簿名称);
debugStatsDump =新的XSSFWorkbook(); //这行需要花费几分钟,显然是在类加载器中???
}
}


解决方案

它事实证明,在某些情况下,当您混合使用来自不同版本的Java(例如1.5和1.8)的jar时,JIT会举手示意并以解释模式运行。甲骨文网站上有几条有关该行为的报告,上面写着我们不知道为什么这么做,我们不会解决。



我下载了源代码对于未在1.8中编译并从源代码构建的库,一切都很好。


It takes 15 minutes or more for POI to initialize its first workbook in Java 8 on Windows 10, in a Tomcat 8 instance. Based on interrupting the process in the debugger and looking at the stack, it is spending the time in the classloader, driven by xbeans.

Edit This has the feel of a classloader issue because when I implemented the workaround for the POI library (below), other classes started expressing the same issue.

Edit The stack trace looks most similar to this bug: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8022063

As you can see in jvisualvm, there is no classloader contention in the process thread taskExecutor-1.

I have a workaround, but it should not be necessary. The accepted answer will explain WHY this is happening.

EDIT: Workaround

During application initialization I added this line to the static class initializer for a configuration bean, to force the classloader to preload the classes and resources. It executes instantly there, and when the actual process is invoked it also executes instantly.

XSSFWorkbook preload = new XSSFWorkbook ();

The final workaround was to preload all of the jar files related to SSL, security, and POI. As near as I can tell, when loaded late in a spring batch context (may be a red herring), the classloader is attempting to validate the bouncycastle jar files with algorithms encoded in the bouncycastle classes, and is running everything in the SSL stack in interpreted mode.

        Reflections reflections = new Reflections("org.bouncycastle", this.getClass().getClassLoader(), new SubTypesScanner(false));
        Set<Class<? extends Object>> bouncyCastleClasses = reflections.getSubTypesOf(Object.class);



        reflections = new Reflections("sun.security", this.getClass().getClassLoader(), new SubTypesScanner(false));
        Set<Class<? extends Object>> sunSecurityClasses = reflections.getSubTypesOf(Object.class);

        reflections = new Reflections("javax.ssl", this.getClass().getClassLoader(), new SubTypesScanner(false));
        Set<Class<? extends Object>> javaSslClasses = reflections.getSubTypesOf(Object.class);

        reflections = new Reflections("org.apache.poi", this.getClass().getClassLoader(), new SubTypesScanner(false));
        Set<Class<? extends Object>> poiClasses = reflections.getSubTypesOf(Object.class);

POM excerpt:

    <poi.version>4.0.1</poi.version>

        <!-- apache poi / poi-ooxml -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>

Code:

public void beforeJob(JobExecution jobExecution) {
    if (logger.isDebugEnabled()) {
        workbookname = "debuginfo-" + System.currentTimeMillis() + ".xlsx";
        logger.debug("Debug statistics dump file will be saved at [{}]", workbookname);
        debugStatsDump = new XSSFWorkbook(); // This line takes several minutes to run, apparently in the classloader???
    }
}

解决方案

It turns out that under some circumstances when you mix jars from different versions of java (say 1.5 and 1.8), the JIT will throw up its hands and run in interpreted mode. There are several reports of the behavior listed on Oracle's website that say "we don't know why it's doing this, we won't fix it".

I downloaded sources for the libraries that were not compiled in 1.8 and built from source, and all is well.

这篇关于Apache POI 4.0.1超级慢入​​门... 15分钟或更长时间。怎么了?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆