实验: metaspace区域OOM
Cglib 动态代理,会动态创建类 如果使用不当会导致生成大量的类元数据 塞满metaspace
试验代码
依赖包
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 模拟元数据区被塞满导致oom
*
* @author holysu 2020/8/11
*/
public class MetaspaceOOM {
/**
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:MetaspaceSize=10M
-XX:MaxMetaspaceSize=10M
-XX:+PrintGCDetails
-Xloggc:gc.log
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
* @param args
*/
public static void main(String[] args) {
int counter = 0;
while (true) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Car.class);
enhancer.setUseCache(false);
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
if (method.getName().equals("run")) {
System.out.println("running, enhanced");
return methodProxy.invokeSuper(o, objects);
} else {
return methodProxy.invokeSuper(o, objects);
}
}
});
Car car = (Car) enhancer.create();
car.run();
System.out.println("目前创建了 " + (counter++) + " 个Car的动态子类");
}
}
static class Car {
public void run() {
System.out.println("running...");
}
}
}
异常信息
执行报错
java.lang.OutOfMemoryError: Metaspace
Dumping heap to ./\java_pid13748.hprof ...
Heap dump file created [2923143 bytes in 0.037 secs]
Exception in thread "main" net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:348)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:117)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:294)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
at MetaspaceOOM.main(MetaspaceOOM.java:42)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339)
... 6 more
Caused by: java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
... 11 more
gc日志
4.669: [GC (Allocation Failure) 4.669: [ParNew: 34944K->2104K(39296K), 0.0033046 secs] 34944K->2104K(126720K), 0.0035844 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
5.218: [GC (Allocation Failure) 5.218: [ParNew: 37048K->2256K(39296K), 0.0051226 secs] 37048K->2256K(126720K), 0.0053311 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
5.633: [GC (Allocation Failure) 5.633: [ParNew: 37200K->2664K(39296K), 0.0101116 secs] 37200K->2664K(126720K), 0.0102989 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Gc日志还是比较清晰的打印出 Metadata 到达阈值引起的fullgc
5.973: [Full GC (Metadata GC Threshold)5.973: [CMS: 0K->2302K(87424K), 0.0538876 secs] 28792K->2302K(126720K), [Metaspace: 9186K->9186K(1058816K)], 0.0543441 secs] [Times: user=0.08 sys=0.03, real=0.06 secs]
6.027: [Full GC (Last ditch collection) 6.027: [CMS: 2302K->1410K(87424K), 0.0168118 secs] 2302K->1410K(126848K), [Metaspace: 9186K->9186K(1058816K)], 0.0169643 secs] [Times: user=0.03 sys=0.00, real=0.02 secs]
6.046: [GC (CMS Initial Mark) [1 CMS-initial-mark: 1410K(87424K)] 1410K(126848K), 0.0003738 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
6.046: [CMS-concurrent-mark-start]
6.089: [CMS-concurrent-mark: 0.014/0.043 secs] [Times: user=0.06 sys=0.00, real=0.04 secs]
6.089: [CMS-concurrent-preclean-start]
6.091: [CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
6.091: [GC (CMS Final Remark) [YG occupancy: 687 K (39424 K)]6.091: [Rescan (parallel) , 0.0003632 secs]6.091: [weak refs processing, 0.0001684 secs]6.091: [class unloading, 0.0022085 secs]6.094: [scrub symbol table, 0.0013801 secs]6.095: [scrub string table, 0.0003217 secs][1 CMS-remark: 1410K(87424K)] 2097K(126848K), 0.0048304 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
6.096: [CMS-concurrent-sweep-start]
6.096: [CMS-concurrent-sweep: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
6.097: [CMS-concurrent-reset-start]
6.099: [CMS-concurrent-reset: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
par new generation total 39424K, used 1038K [0x0000000081200000, 0x0000000083cc0000, 0x0000000095ec0000)
eden space 35072K, 2% used [0x0000000081200000, 0x0000000081303890, 0x0000000083440000)
from space 4352K, 0% used [0x0000000083440000, 0x0000000083440000, 0x0000000083880000)
to space 4352K, 0% used [0x0000000083880000, 0x0000000083880000, 0x0000000083cc0000)
concurrent mark-sweep generation total 87424K, used 1410K [0x0000000095ec0000, 0x000000009b420000, 0x0000000100000000)
Metaspace used 9214K, capacity 10134K, committed 10240K, reserved 1058816K
class space used 790K, capacity 841K, committed 896K, reserved 1048576K
到底是什么东西在元数据?
通过mat分析oom时候自动dump的文件
首先发现应用程序类加载器 AppClassLoader 加载了很多东西
发现有大量 CGLib 相关的类以及 生成的Car类 class MetaspaceOOM\(Car\)\(EnhancerByCGLib\)xxx
cglib 总共动态生成了 668个类
list outgoing objects 进去看,这个名字怪怪的类 父类是 Car, 关联了一堆 cglib的代理对象 也就是说肯定是通过cglib加强 car 的时候有问题
本文来自博客园,作者:mushishi,转载请注明原文链接:https://www.cnblogs.com/mushishi/p/14553136.html