springboot LaunchedURLClassLoader throws error class exceeds the maximum class size supported by JVM(常量池太大)

springboot LaunchedURLClassLoader throws error class exceeds the maximum class size supported by the JVM (constant pool too big)

我有一个遗留应用程序,其中一个 java 文件有大约 280000 行。我有一个用于 restful 服务的 spring 启动应用程序,其中一个服务调用如此巨大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.access0(URLClassLoader.java:73)
        at java.net.URLClassLoader.run(URLClassLoader.java:368)
        at java.net.URLClassLoader.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 转换原始字节码,向其添加额外的指令和数据。所以你的怪物 class - 谁会写出如此疯狂的大 class 而不会因为自称程序员而感到羞耻? - 只是变得太大了,因为它可能接近 JVM per-class 大小限制开始。

你能做什么?那得看情况了:

  • 将 class 重构为更小的部分,用自动化测试覆盖重构,确保 broken-down 之后的事情和以前一样。不管是否遗留,代码就是代码,你可以修改它。

  • 如果出于某种原因你太害怕,不熟练或懒惰重构并且幸运的是怪物class实际上不需要任何方面的建议,你可以修改你的切入点不那么全局化,更具体,不包括怪物 class 或者甚至更大的遗留包,这取决于你的用例。