在将Spring应用程序maven构建升级到Java 11之后,我们看到java进程的内存消耗不断增加。
工作良好:用Java 8构建JDK +在服务器上运行Java 11
有漏洞:用Java 11构建+在服务器上运行Java 11
泄漏在堆转储甚至本机内存跟踪中都是不可见的,直到物理内存+交换空间满了,进程被系统杀死为止,进程一直在增加。究竟是甚麽问题造成了这类问题呢?
发布于 2020-05-20 20:42:08
在Java11中,ForkJoinPool类的行为略有不同。
最后一次使用线程之前的默认运行时间是60秒。在Java 8中,这是无文档化的,但实际上是在2秒内硬编码的。在超大池的情况下,Java 8实现在池创建两秒钟后终止空闲线程。但是Java 9/11版本的类使它们保持几分钟的活力。
比较线程的数量和生存期。由于在启动应用程序或创建ForkJoinPools对象时,可能不再提前终止未使用的线程,因此线程的延长生存期很容易导致内存问题。
有关类似的问题,请参见以下问题:ForkJoinPool性能Java8 vs 11
在Java9中引入了一个新构造函数来配置该值。要获得与Java8编译相同的行为,您必须在编译到Java9之前显式地将keepAliveTime设置为2秒或缩小ForkJoinPool对象的大小。
发布于 2020-05-24 16:14:23
在深入研究Java的编译器代码之后,我发现了一个有趣的变化,它是在Java 9中引入的,我还没有意识到。此更改可能导致不同的行为,具体取决于编译目标:
虽然众所周知,大多数优化都是由JIT编译器而不是javac完成的,但后者仍然进行了一些代码优化。在Java 9之前,这些优化之一是将字符串连接转换为StringBuilder::append链。从Java 9开始,javac使用了对新引入的java.lang.invoke.StringConcatFactory类的invokedynamic调用,而不是转换到StringBuilder:append调用。因此,当您编译到Java 8时,javac将生成优化的字节代码,而当您编译到Java 9时,优化将在运行时委托给上述内置类。
相应的9月280提供了有关此更改的更多详细信息。JEP 280的一个成功标准是字符串连接性能绝不能倒退。但是JDK-8221760已经报告了一个潜在的性能倒退。根据bug条目,编译到Java 8的字符串级联代码在Java 11u上的性能似乎比编译到Java 9或11的相同代码执行得更好。bug条目仍未解决,因此性能可能不是这里唯一的倒退。
https://stackoverflow.com/questions/61819165
复制相似问题