Для POI требуется 15 минут или более, чтобы инициализировать свою первую книгу на Java 8 в Windows 10 в экземпляре Tomcat 8. Основываясь на прерывании процесса в отладчике и просмотре стека, он проводит время в загрузчике классов, управляемом xbeans.
Редактировать
Это похоже на проблему загрузчика классов, потому что когда я реализовал обходной путь для библиотеки POI (ниже), другие классы начали выражать ту же проблему.
Редактировать
Трассировка стека наиболее похожа на эту ошибку: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8022063
Как вы можете видеть в jvisualvm, в потоке процессов taskExecutor-1 нет конфликта загрузчика классов.
У меня есть обходной путь, но он не должен быть необходим. Принятый ответ объяснит ПОЧЕМУ это происходит.
РЕДАКТИРОВАТЬ: Обходной путь
Во время инициализации приложения я добавил эту строку в инициализатор статического класса для bean-компонента конфигурации, чтобы заставить загрузчик классов предварительно загружать классы и ресурсы. Там он выполняется мгновенно, а когда вызывается реальный процесс, он также запускается мгновенно.
XSSFWorkbook preload = new XSSFWorkbook ();
Последний обходной путь - предварительная загрузка всех jar-файлов, связанных с SSL, безопасностью и POI. Насколько я могу судить, при поздней загрузке в контексте весеннего пакета (может быть красная сельдь) загрузчик классов пытается проверить файлы jar bouncycastle с помощью алгоритмов, закодированных в классах bouncycastle, и выполняет все в стеке SSL в интерпретируемый режим.
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:
<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("Debug statistics dump file will be saved at [{}]", workbookname);
debugStatsDump = new XSSFWorkbook(); // This line takes several minutes to run, apparently in the classloader???
}
}