【问题标题】:java.lang.OutOfMemoryError: Compressed class spacejava.lang.OutOfMemoryError:压缩的类空间
【发布时间】:2015-05-28 15:51:22
【问题描述】:

我们在 java-8-oracle 上运行。

六个月前我们搬到了 java8。

在过去的几天里,我们不时收到 OOME,但我们无法识别或重现问题。

当我们执行对服务器 (tomcat) 的调用时,我们会在堆栈跟踪中收到此错误:

java.lang.OutOfMemoryError: Compressed class space

重启服务器即可解决问题。对其他服务器的相同调用有效,对同一服务器的另一种类型的另一个调用也是如此。

查看 gc.log 时,我们看到:

2015-05-27T16:05:42.991+0000: 98774.440: [Full GC (Last ditch collection) 98774.440: [CMS: 575745K->575330K(3495936K), 0.8687777 secs] 575745K->575330K(4107008K), [Metaspace: 97940K->97940K(1396736K)], 0.8696093 secs] [Times: user=0.95 sys=0.00, real=0.88 secs]
2015-05-27T16:05:55.486+0000: 98786.935: [Full GC (Metadata GC Threshold) 98786.935: [CMS: 573414K->578735K(3495936K), 0.9372859 secs] 925046K->578735K(4107008K), [Metaspace: 99428K->99428K(1396736K)], 0.9386626 secs] [Times: user=1.01 sys=0.00, real=0.94 secs]

jstat -gc 返回:

 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
87296.0 87296.0  0.0   3151.4 523776.0 148284.4 3495936.0   574868.5  1395640.0 98066.3 1048576.0 11339.1  12165  636.851  223   116.957  

753.808

我在 jstat 日志或 gc 日志中都没有看到任何内存问题。

尝试运行jmap -clstats 挂起:

Attaching to process ID 5110, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.25-b02
finding class loader instances ..

【问题讨论】:

  • 您使用哪些 Xms 和 Xmx 开关启动 JVM?我建议您使用 visualvm 或类似工具来更好地查看和了​​解您的 JVM 大小是如何设置的。或者使用 Eclipse 内存分析器。暂时你可以尝试使用 -XX: CompressedClassSpaceSize 来增加压缩类空间。为了更好地分析问题,您应该将 JVM 设置为 OOME 上的堆转储。
  • 您在什么时间段后看到此异常?您是否尝试增加 CompressedClassSpace?例如:-XX: CompressedClassSpaceSize=1g ?如果您再次看到问题,但经过较长时间后,您似乎有某种内存泄漏。
  • @DavidG - 2 天前在其中一个服务器中第一次遇到(我们没有部署新版本)。重新启动服务器,然后在 12 小时后仅在其中一台服务器上再次看到它。压力负载不有助于重现。压缩大小几乎保持不变,并且不接近默认值 1G。
  • 这可能是一个 JVM 错误。 hotspot-gc-dev discussion 存在类似症状的问题。尝试tuning 元空间增长-收缩策略。

标签: java garbage-collection jvm out-of-memory java-8


【解决方案1】:

我们遇到了类似的问题。不幸的是,堆转储不会帮助您,因为类不在堆中,而是在本机内存中。在您的 JVM 设置中启用这些以对加载的类进行故障排除:

-XX:+PrintGCDetails -XX:+TraceClassUnloading -XX:+TraceClassLoading

在我们的例子中,问题是 JAXBContext.newInstance 不是单例。

祝你好运, 阿尔伯特

【讨论】:

    【解决方案2】:

    您可以使用以下两个选项之一来解决此问题。

    1.您可以通过使用 -XX:CompressedClassSpaceSize=n VM 标志来增加类空间的限制。最大限制为 4GB。

    (或)

    2。您可以使用 -XX:-UseCompressedClassPointers VM 标志完全禁用压缩类指针功能。

    注意:请注意,禁用此功能会增加应用程序的堆空间使用率。

    来自“Java 性能优化:压缩的 OOPS”一书

    每个对象都有一个指向 VM 元数据类的指针 (_klass)。这个指针 也在 64 位 JVM 上压缩。在 JDK 8 中,永久代是 被元空间内存删除并替换。这个元空间是 动态增长的内存,如果 VM 可以达到本机内存限制 标志未配置为控制此元空间内存。以前的 Java 8,使用永久内存,其大小由 VM 标志固定。它 无法在运行时更改其大小。与堆内存相比 空间,这个永久内存空间(非堆)非常小,将 通常在 4GB 限制内存储类元数据和其他 元数据。所以虚拟内存地址范围可以是 0 到 4 GB,如果 从零开始的虚拟内存由操作系统分配给这个 永久记忆。所以压缩klass对象的内存地址 在这个永久内存位置只使用 32 位是没有问题的。

    但是在 Java 8 中,永久内存被替换为元空间,以便 支持一些性能改进。这个内存位置可以增长 如果 -XX: MaxMetaspaceSize VM 是,直到它达到本机内存限制 没有设置来控制这种增长。如果它可以增长到原生内存 限制,那么类对象也可能存储在任何更高的位置 内存边界。这将是压缩该内存的问题 位置使用 32 位偏移量。所以为了处理这个问题 单独为 klass 实例分配单独的内存空间,Java 在 Java 中引入了一种称为“压缩类空间”的新内存空间 8 版本。在 Java 8 中包含压缩的类空间内存 介绍了“Java.lang.OutOfMemoryError:压缩的类空间”。这个 OutOfMemoryError 在压缩类空间内存时触发 达到其最大默认容量 1 GB 并且没有更多 存储额外的类实例的空间

    要了解有关此 OutOfMemoryError 和 klass 归档的更多详细信息,您可以阅读以下书籍。

    https://javaperformanceoptimization.com/

    1. Java 性能优化:压缩的 OOPS
    2. Java 性能优化:如何避免 10 个 OutOfMemoryErrors

    【讨论】:

      【解决方案3】:

      使用压缩的 oops 和压缩的类指针,类的可用空间由于必要的指针修改而受到限制。你的情况是 1GB。

      有很多类,所以这可能表明您的应用程序中的某些东西正在创建很多类并且从未释放它们。可能会重新加载应用程序?

      如果您确定您的应用程序只需要那么多内存用于类,您可以尝试通过-XX:CompressedClassSpaceSize=... 提高限制或通过-XX:-UseCompressedClassPointers 禁用压缩类指针。

      请注意,默认压缩类空间 + 压缩堆(+ 一些开销)不能超过 32GB。虽然,AIUI,改变对象对齐可能会进一步突破这个限制。

      否则,您应该进行堆转储并分析加载的类中保存的内容。

      【讨论】:

      • 在jstat日志中可以看到CCSU是1048576.0,CCSU是11339.1。
      • 可能是碎片?我不认为课堂空间变得紧凑。虽然如此巨大的因素很奇怪,即使它是碎片化的。另外,我认为您偏离了一栏,但仍然存在差异。
      • 你可以运行它来检查我在列中是否有错误: echo "S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT\n 87296.0 87296.0 0.0 3151.4 523776.0 148284.4 3495936.07485. 1395640.0 98066.3 1048576.0 11339.1 12165 636.851 223 116.957 753.808" |列-t
      • 你是对的。很奇怪。尽管如此,请尝试这些选项,并按照@Marged 的​​建议在 OOME 上启用堆转储。至少它应该有助于进一步诊断。
      猜你喜欢
      • 2016-05-11
      • 1970-01-01
      • 2011-09-04
      • 2017-02-16
      • 2011-10-24
      • 2012-07-31
      • 2019-08-08
      相关资源
      最近更新 更多