Metaspace介绍
jdk8以及以后的版本中,使用Metaspace代替了永久代,Metaspace是方法区在HotSpot中的实现,与永久代的最大区别在于,Metaspace使用本地内存,而不是JVM分配的虚拟内存。
永久代(JDK8后的元空间)存储了以下信息:
- 虚拟机加载的类信息
- 常量池
- 静态变量
- 即使编译后的代码
查看元空间大小
java -XX:+PrintFlagsInitial | grep Metaspace
元空间溢出模拟
-
将元空间设置为10M
-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
-
配置依赖
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.9.RELEASE</version> </dependency> </dependencies>
-
代码
import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; /** * @title MetaspaceDemo * @description 模拟元空间溢出 * author zzw * version 1.0.0 * create 2024/8/10 10:29 **/ public class MetaspaceDemo { static class OOM{} public static void main(String[] args) { int i = 0; // 用于计数,查看放入多少个类信息后发生异常 try { while (true) { i++; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOM.class); enhancer.setUseCache(false); enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> methodProxy.invokeSuper(o, args)); enhancer.create(); } } catch (Exception e) { e.printStackTrace(); } finally { System.out.println("====================>>发生异常的次数:" + i); } } }
-
运行结果
====================>>发生异常的次数:540 Exception in thread "main" java.lang.OutOfMemoryError: Metaspace at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:538) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:131) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572) at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:387) at com.doudou.jdk.MetaspaceDemo.main(MetaspaceDemo.java:33)