spring-boot - springboot LaunchedURLClassLoader throws error class超过了JVM支持的最大类大小(常量池太大)
问题描述
我有一个遗留应用程序,其中一个 java 文件有大约 280000 行。我有一个用于 restful 服务的 spring boot 应用程序,其中一个服务调用这个巨大的 JAVA 文件。当我在没有 aspectjweaver 的情况下加载应用程序时,应用程序工作正常,但当我在 java 选项中指定 javaagent 时失败。我已经尝试过 JVM 堆,但它没有帮助。
以下是错误堆栈跟踪:
[LaunchedURLClassLoader@7cbd213e] error at MYCLASS.java::0 The class MYCLASS exceeds the maximum class size supported by the JVM (constant pool too big).
Aug 14, 2020 3:42:01 PM org.aspectj.weaver.tools.Jdk14Trace error
SEVERE: MYCLASS
java.lang.RuntimeException: key not found in wovenClassFile
at org.aspectj.weaver.WeaverStateInfo.findEndOfKey(WeaverStateInfo.java:408)
at org.aspectj.weaver.WeaverStateInfo.replaceKeyWithDiff(WeaverStateInfo.java:364)
at org.aspectj.weaver.bcel.LazyClassGen.getJavaClassBytesIncludingReweavable(LazyClassGen.java:711)
at org.aspectj.weaver.bcel.BcelWeaver.getClassFilesFor(BcelWeaver.java:1448)
at org.aspectj.weaver.bcel.BcelWeaver.weaveAndNotify(BcelWeaver.java:1410)
at org.aspectj.weaver.bcel.BcelWeaver.weave(BcelWeaver.java:1188)
at org.aspectj.weaver.tools.WeavingAdaptor.getWovenBytes(WeavingAdaptor.java:527)
at org.aspectj.weaver.tools.WeavingAdaptor.weaveClass(WeavingAdaptor.java:363)
at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:121)
at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:54)
at sun.instrument.TransformerManager.transform(TransformerManager.java:188)
at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:428)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
at java.lang.Class.getDeclaredConstructors(Class.java:2020)
at com.fasterxml.jackson.databind.util.ClassUtil.getConstructors(ClassUtil.java:1162)
at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector._findPotentialConstructors(AnnotatedCreatorCollector.java:101)
at com.fasterxml.jackson.databind.introspect.AnnotatedCreatorCollector.collect(AnnotatedCreatorCollector.java:56)
解决方案
AspectJ 转换原始字节码,向其中添加额外的指令和数据。所以你的怪物类——谁会写一个如此疯狂的大类而不以称自己为程序员为耻?- 只是变得太大了,因为它可能一开始就接近 JVM 每个类的大小限制。
你能做什么?好吧,这取决于情况:
将类重构为更小的部分,使用自动化测试覆盖重构,确保分解后的内容与之前一样。无论是否遗留,代码就是代码,您可以修改它。
如果由于某种原因你太害怕、不熟练或懒得重构并且幸运的是怪物类实际上不需要任何方面的建议,你可以修改你的切入点,使其不那么全局和更具体,不包括怪物类甚至可能是遗留包的更大部分,具体取决于您的用例。
推荐阅读
- c# - Asp.net 类库核心引用一个 web 表单应用程序
- c++ - 使用 std::initializer_list 构造用 std::optional 包装的 std::map
- sql - PostgreSQL 数据转换 - 将行变成列
- c - 是否可以通过 SIGFPE FPE_INTOVF 在 C (POSIX/Linux) 中捕获整数溢出异常?
- firebase - 我可以将经过 Google 身份验证的用户添加到 Firebase 中的用户列表吗?
- git - 提交文件以回滚 - Heroku
- xcode - 如何在 Xcode 13.0 版上删除目标
- java - 需要帮助理解这个数组方法调用
- flask - 在python中加载环境变量
- c# - C# 新手,如何更新数据表(或连接表)?