JMM

作者: Sandy_678f | 来源:发表于2020-05-11 15:32 被阅读0次

    Java Memory Model ,JMM Java内存模型
    (图片来源于网络,侵删。)


    image.png
    1. 程序计数器
    2. Java虚拟机栈
    3. 本地方法栈
    4. 方法区

    程序计数器,Java虚拟机栈,本地方法栈是线程私有的。
    方法区,堆是线程共享的。

    1. 程序计数器
    这块区域是虚拟机规范中唯一没有OutOfMemory错误的区域
    
    1. Java虚拟机栈
      描述的是Java方法执行的内存模型:每个方法执行的同时会创建一个栈帧。
      栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。
    1)线程请求的栈深度大于虚拟机允许的栈深度,将抛出StackOverflowError
    2)虚拟机栈空间可以动态扩展,当动态扩展无法申请到足够的空间时,则抛出OutOfMemory异常
    
    1. 本地方法栈
      本地方法栈与虚拟机栈发挥的作用十分相似,区别是虚拟机栈执行的是Java方法(也就是字节码)服务,而本地方法栈则为虚拟机使用到的native方法服务,可能底层调用的c或者c++,我们打开jdk安装目录可以看到也有很多用c编写的文件,可能就是native方法所调用的c代码。


    2. 堆是java虚拟机管理内存最大的一块内存区域,因为堆存放的对象是线程共享的,所以多线程的时候也需要同步机制
      它是所有线程共享的,它的目的是存放对象实例。同时它也是GC所管理的主要区域,因此常被称为GC堆。当前主流的虚拟机如HotPot都能按扩展实现(通过设置 -Xmx和-Xms)。

    如果堆中没有内存内存完成实例分配,而且堆无法扩展将报OOM错误(OutOfMemoryError)
    
    1. 方法区
      用于存储已被虚拟机加载的类信息、常量、静态变量,如static修饰的变量加载类的时候就被加载到方法区中。
    运行时常量池
    是方法区的一部分,class文件除了有类的字段、接口、方法等描述信息之外,还有常量池用于存放编译期间生成的各种字面量和符号引用。
    

    溢出的两个基本例子:

    public class MemErrorTest {
    
        public static void hi(){
            hi();
        }
    
        public static void main(String[] args) {
            try{
                List<Object> list = new ArrayList<Object>();
                for(;;){
                    //创建对象速度可能高于JVM
                    list.add(new Object());
                }
            }catch (OutOfMemoryError e){
                e.printStackTrace();
            }
    
            try{
                //递归造成StackOverflowError 这边因为每运行一个方法将创建一个栈帧
                hi();
            }catch (StackOverflowError e){
                e.printStackTrace();
            }
        }
    }
    

    运行结果:

    java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:3210)
        at java.util.Arrays.copyOf(Arrays.java:3181)
        at java.util.ArrayList.grow(ArrayList.java:265)
        at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
        at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
        at java.util.ArrayList.add(ArrayList.java:462)
        at menerror.MemErrorTest.main(MemErrorTest.java:24)
    java.lang.StackOverflowError
        at menerror.MemErrorTest.hi(MemErrorTest.java:16)
        at menerror.MemErrorTest.hi(MemErrorTest.java:16)
        at menerror.MemErrorTest.hi(MemErrorTest.java:16)
    ……
    

    相关文章

      网友评论

          本文标题:JMM

          本文链接:https://www.haomeiwen.com/subject/pxrunhtx.html