跳转至

Metaspace 元空间

  • JVM参数

    -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m

  • Java 8 之后的版本使用Metaspace来替代永久带.

  • Meatspace是方法区在HotSpot中的实现 , 它与持久带最大的区别在于 : Metaspace 并不在虚拟机内存中而是使用本地内存

  • 即在 java 8 中, classe metadata (the virtual machines internal presentation of java class) , 被存储在叫做Metaspace的Native memory 中

  • 永久代 (java 8 后被元空间替代了)存放了以下信息:

    1. 虚拟机加载的类信息
    2. 常量池
    3. 静态变量
    4. 即时编译后的代码

模拟Metaspace空间溢出 , 我们不断地生成类王远空间里灌 , 类占据的空间总是会超过Metaspace指定的空间大小

示例

  • 调小元空间大小 (以便观察)

    -XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m

  • 引入GCbil

    ```java import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;

    import java.lang.reflect.Method;

    public class metaspace { static class OOMTest{} public static void main(String[] args) throws Exception { int i = 0; try { while (true){ i++; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(OOMTest.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { return methodProxy.invokeSuper(o,args); } }); enhancer.create(); } } catch (Throwable e) { System.out.println("****************第" + i + "发生异常"); e.printStackTrace(); } } }

    ```

    cmd ****************第73发生异常 java.lang.OutOfMemoryError: Metaspace at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:467) at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:339) 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 metaspace.main(metaspace.java:23)