我想用
jdk.internal.loader.ClassLoaders$AppClassLoader
代替弹簧靴 org.springframework.boot.loader.LaunchedURLClassLoader
。但是,我不确定这将如何影响 spring-boot 运行时。
我们最近在 java 的
java.lang.InstantiationError
内进行 Spring 存储库调用时遇到了 parallelStream()
。我了解到并行流中的线程正在使用 AppClassLoader
,因此无法找到位于 LaunchedURLClassLoader
(类加载器层次结构中 AppClassLoader
的子级)中的应用程序类。
spring-boot 文档 显示您可以在不使用类加载器的情况下运行解压的 spring-boot jar。这很方便地意味着应用程序类也被加载到
AppClassLoader
中,从而解决了 parallelStream()
的问题。
$ java -cp BOOT-INF/classes:BOOT-INF/lib/* com.example.MyApplication
NB:这也是 Intellij IDEA 运行 spring-boot 应用程序的方式。
谁知道 spring-boot 类加载器是否所做的不仅仅是启用我应该了解的可执行 jar 和 war 文件。我发现文档不够明确。在生产中不使用 spring-boot 类加载器是否安全?
我还遇到了间歇性问题,突然使用 AppClassLoader 而不是 LaunchedURLClassLoader(甚至在并行执行之外),导致找不到资源。
最新版本的文档有一个“高效部署”部分,表示运行解压的存档会更快。
某些 PaaS 实现也可能选择在运行之前解压存档。例如,Cloud Foundry 就是这样运作的。安全的。 我什至会说它更安全,因为它在运行时会更简单,但这是我的拙见。知道了这一点,我可以说在生产中这样做绝对是
还补充说:
解压 jar 文件后,您还可以通过使用其“自然”主方法运行应用程序来获得额外的启动时间 [...]:
正如你所说,这方便地意味着我们摆脱了 Spring Boot 自定义 ClassLoader!只有一个注释:
$ jar -xf myapp.jar $ java -cp "BOOT-INF/classes:BOOT-INF/lib/*" com.example.MyApplication
在应用程序的 main 方法上使用 JarLauncher 具有可预测的类路径顺序的额外好处。该 jar 包含一个 classpath.idx 文件,JarLauncher 在构建类路径时使用该文件。
因此,在使用“自然”的 main 方法时,请注意不可预测的类路径顺序。这似乎是唯一的缺点。
更进一步:
URLClassLoader
的LaunchedURLClassLoader,并分析 LaunchedURLClassLoaderTests 中的测试,我可以说它只是添加了处理 JAR 资源加载和嵌套 JAR 的逻辑。过去曾通过添加“快速异常”机制修复了像#4582这样的性能问题。