• JVM各区域的用途


    程序计数器

    用于给字节码解释器来选取吓一跳需要执行的字节码指令。每个线程有一个独立的程序计数器去,且各个线程之间互不影响。如果线程正在执行一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的内存地址;如果执行的是Native方法。在计数器为Undefined。此区域是JVM规范中唯一一个不存在OOM(内存溢出)的区域。


    虚拟机栈(局部变量空间)

    存放编译器可知的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象应用(reference)。64位的double、long占用2个槽。内存空间在编译期间就能确定,当进入一个方式时,这个方法需要分配的局部变量空间是完全确定的,通过-Xss设置内存容量。
    异常状况:
    - StackOverflowError栈深度大于虚拟机所允许的深。
    - OOM 如果虚拟机栈可以动态扩展(当前大部分Java虚拟机都可以动态扩展,只不过Java虚拟机规范中的也允许固定长度的虚拟机栈),如果扩展是无法申请到足够的内存。


    本地方法栈

    跟虚拟机栈类似,只是一个是虚拟机执行Java方法,一个是执行Native方法

    异常状况:

    • StackOverflowError 栈深度大于虚拟机所允许的深度
    • OOM(内存溢出)

    Java堆

    线程共享的一块内存区域,从内存回收角度来看,基本都采用分代收集算法,所以分为新生代、老年代。再细致一点可以分为Eden空间、From Survivor空间、To Survivor空间等。-Xmx-Xms控制堆空间大小。

    异常状况:
    - OOM(内存耗尽) 堆无法扩展时。

    /**
     * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
     * 
     * java.lang.OutOfMemoryError: Java heap space
     */
    public class HeapOOM {
    
        static class OOMObject {
        }
    
        public static void main(String[] args) {
            List<OOMObject> list = new ArrayList<OOMObject>();
    
            while (true) {
                list.add(new OOMObject());
            }
        }
    }

    方法区

    线程间共享。存储已经被虚拟机加载的类信息、常量、静态变量、即时编辑器编译后的代码等数据,在HotSpot虚拟机中可以称为永生代。运行时常量也是方法区的一部分(String.intern()动态加入常量池)-XX:MaxPermSize控制大小。

    异常状况:
    - OOM

    /**
    * VM Args:-XX:PermSize=10M -XX:MaxPermSize=10M
    *
    * java.lang.OutOfMemoryError:PermGen space
    */
    public class RuntimeConstantPoolOOM {
    
    public static void main(String[] args) {
        // 使用List保持着常量池引用,避免Full GC回收常量池行为
        List<String> list = new ArrayList<String>();
        // 10MB的PermSize在integer范围内足够产生OOM了
        int i = 0;
        while (true) {
            list.add(String.valueOf(i++).intern());
        }
    }
    }

    直接内存(不属于虚拟机运行时的数据区的一部分)

    NIO可以使用Native函数库直接分配对外的内存,然后通过存储在Java对中的DirectByteBuffer对象作为这块内存的引用进行操作。受限于机器物理内存,可以通过-XX:MaxDirectMemorySize制定,如果不制定,默认与Java堆最大值(-Xmx)一样。
    异常状况:
    - OOM

    public class DirectMemoryOOM {
    
        private static final int _1MB = 1024 * 1024;
    
        public static void main(String[] args) throws Exception {
            Field unsafeField = Unsafe.class.getDeclaredFields()[0];
            unsafeField.setAccessible(true);
            Unsafe unsafe = (Unsafe) unsafeField.get(null);
            while (true) {
                unsafe.allocateMemory(_1MB);
            }
        }
    }

    作者: haifeiWu

    出处: http://www.hchstudio.cn/

    关于作者:专注大后端,分布式,高并发等领域,请多多赐教!

    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接

  • 相关阅读:
    c# 自定義事件
    c# 判斷事件中鼠標的左右按鍵
    I swear(我發誓)
    SQL Server实用操作小技巧集合
    富人和穷人的经典差异
    Mssql入门语句
    c# 匿名方法學習
    SOS: Autodesk MapGuide Studio Preview can not display "Feature Label" with Chinese text on the platform of MapGuide Open Source
    MapGuide open source开发心得二: 资源
    moblie development based on .net compact framework2 solution:activeX
  • 原文地址:https://www.cnblogs.com/haifeiWu/p/9079600.html
Copyright © 2020-2023  润新知