记一次JVM内存溢出解决过程

本文记录了一次由于大量类加载导致JVM Compressed Class Space溢出的问题,分析了UseCompressedClassPointers和UseCompressedOops选项,以及如何通过调整JVM参数解决这个问题。使用Java VisualVM和MAT工具定位到内存泄露源头为ShardingJDBC的Groovy动态编译。最终通过升级Sharding JDBC版本至3.1.0解决了内存持续增长的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.问题简述

线上的服务器随着访问量的增加莫名其妙的挂了查看了一下错误日志:

java.lang.OutOfMemoryError: Compressed class space

2.问题分析

在Java8以前,有一个选项是UseCompressedOops。所谓OOPS是指“ordinary object pointers“,就是原始指针。Java Runtime可以用这个指针直接访问指针对应的内存,做相应的操作(比如发起GC时做copy and sweep)。
那么Compressed是啥意思?64bit的JVM出现后,OOPS的尺寸也变成了64bit,比之前的大了一倍。这会引入性能损耗——占的内存double了,并且同尺寸的CPU Cache要少存一倍的OOPS。
于是就有了UseCompressedOops这个选项。打开后,OOPS变成了32bit。但32bit的base是8,所以能引用的空间是32GB——这远大于目前经常给jvm进程内存分配的空间。
到了Java8,永久代被干掉了,有了“meta space”的概念,存储jvm中的元数据,包括byte code,class等信息。Java8在UseCompressedOops之外,额外增加了一个新选项叫做UseCompressedClassPointer。这个选项打开后,class信息中的指针也用32bit的Compressed版本。而这些指针指向的空间被称作“Compressed Class Space”。默认大小是1G,但可以通过“CompressedClassSpaceSize”调整。

如果你的java程序引用了太多的包,有可能会

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值