【问题标题】:Java 8 Metaspace: OutOfMemoryError: Dealing with reflection InflationJava 8 元空间:OutOfMemoryError:处理反射膨胀
【发布时间】:2017-07-05 17:04:04
【问题描述】:

网络上有很多links和打开Q&A,但我仍然缺少很多信息。

第一件事

问题:

java.lang.OutOfMemoryError: 元空间

jvm:

java version:  "1.8.0_131"
vm:             Java HotSpot(TM) 64-Bit Server
vm args:       -Xms1024m -Xmx1024m -XX:MaxMetaspaceSize=128m

框架:

春天、冬眠、检票口、码头

嫌疑人1:

在使用期间,元空间逐渐增长,以下反射类按比例加载到元空间中[通过 jmap -histo cron 作业观察]

sun.reflect.GeneratedConstructorAccessor1299
sun.reflect.GeneratedMethodAccessor6929
sun.reflect.GeneratedSerializationConstructorAccessor4220

可能的解决方案:

一个。由于我们正在使用大量处理反射内容的库,我们认为 128m 不足以在元空间中保存所有生成的XX类。所以我们计划将元空间限制加倍。 -XX:MaxMetaspaceSize=256m

b.我们考虑设置以下内容

-D sun.reflect.noInflation

-D sun.reflect.inflationThreshold

嫌疑人2:

Full GC 甚至在它到达/占用完整配置的元空间 (128m) 之前一直在持续运行,并且应用程序变得无响应/缓慢/有时 OOM,因为 jvm 只执行 FGC。

[Full GC (元数据 GC Threshold) [PSYoungGen: 224K->0K(698368K)] [ParOldGen: 52910K->52933K(1398272K)] 53134K->52933K(2096640K), [元空间:92733K->92733K(1163264K)],0.1964143 秒] [次数: user=0.59 sys=0.00, real=0.19 secs]

.

使用的元空间 147414K,容量 155731K,提交 159616K, 保留 1187840K
类空间使用17242K,容量19252K, 已提交 20352K,保留 1048576K

可能的解决方案:

-XX:CompressedClassSpaceSize 在 vm 启动时没有明确提及,这可能会导致过度保留地址空间,从而导致误导已提交的空间,从而导致完全 GC。所以明确设置 -XX:CompressedClassSpaceSize=256m 将帮助 vm 进行正确的内存规划和保留。

问题:

  1. 嫌疑人 1:是否有人遇到过类似问题并得到任何解决?
  2. 怀疑 2:设置 -XX:CompressedClassSpaceSize 真的会影响元空间规划/保留并影响 GC 吗?有什么指点吗?
  3. 还有其他嫌疑人吗?推荐?

【问题讨论】:

  • -XX:CompressedClassSpaceSize 在 vm 启动时未明确提及,这可能会导致过度保留地址空间,从而导致误导性已提交空间 - 保留空间不计入已提交空间数字/RSS/WSS。
  • 只需删除 -XX:MaxMetaspaceSize=… 选项。元空间最大的特点之一是可以调整大小。如果您想“帮助 vm 进行正确的内存规划和保留”,请不要对其施加任意限制。
  • 但是当真正的类泄漏时,风险会更大。

标签: java spring reflection garbage-collection out-of-memory


【解决方案1】:

花了这么多时间,事实证明没有类泄漏,我们是受害者

Reflection Inflation

package sun.reflect;

/**
 The master factory for all reflective objects, both those in
 java.lang.reflect (Fields, Methods, Constructors) as well as their
 delegates (FieldAccessors, MethodAccessors, ConstructorAccessors).
**/

public class ReflectionFactory {


    // "Inflation" mechanism. Loading bytecodes to implement Method.invoke() and Constructor.newInstance() currently costs
    // 3-4x more than an invocation via native code for the first invocation (though subsequent invocations have been benchmarked
    // to be over 20x faster). Unfortunately this cost increases startup time for certain applications that use reflection
    // intensively (but only once per class) to bootstrap themselves. To avoid this penalty we reuse the existing JVM entry points
    // for the first few invocations of Methods and Constructors and then switch to the bytecode-based implementations.

我亲自验证过,在每 16 次反射生成时,都会使用该技术来改善响应时间。

最后我们增加了元空间,一切似乎都正常了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多