转载

JVM深入理解(三)内存模型

背景

对于JVM这块儿的知识,我估计大部分的都是只有在需要面试的时候才会拿出来复习一下,然后就又放下来。也是因为这块儿是 Java 最底层的部分,非常难懂。其实如果真的说认真、细心的去撸一下,了解透彻,应该就不会那么容易忘记。

今天的主要目的也是根据 Oracle 的官方文档来一步一步的理解与学习,并且用用一些 demo 来验证理论。

我们先来看一下JVM的一个架构图:

JVM深入理解(三)内存模型

堆的划分

我们首先看一下官方地址对于运行时数据区域的一个划分: https://docs.oracle.com/javase/specs/jvms/se8/html/index.html

2.5. Run-Time Data Areas

  • 2.5.1. The pc Register
  • 2.5.2. Java Virtual Machine Stacks
  • 2.5.3. Heap
  • 2.5.4. Method Area
  • 2.5.5. Run-Time Constant Pool
  • 2.5.6. Native Method Stacks

堆存放:对象、数组 (官方证明: The heap is the run-time data area from which memory for all class instances and arrays is allocated. )

方法区

方法区存放:静态成员变量、常量、类的信息、常量池 (官方证明: It stores per-class structures such as the run-time constant pool, field and method data, and the code for methods and constructors, including the special methods ( §2.9 ) used in class and instance initialization and interface initialization.)

Java虚拟机栈

然后我们看一段代码:

public void a(){
        System.out.println("this is a methd");
        b();
    }

    private void b() {
        System.out.println("this is b methd");
        c();
    }

    private void c() {
        System.out.println("this is c methd");
    }

JVM深入理解(三)内存模型

其实在这就可以看到,因为有相互调用的情况,这里利用栈的原理(FILO=frist in last out)。

  • 先a()入栈发现调用了b(),b()入栈发现调用c();
  • c()执行完毕出栈,然后b()出栈,最后c()方法出栈;

如果一直压栈的话,如果是无穷的递归会怎么办?所以栈是需要规定深度的,对应的就是栈的大小-Xss来控制的,如果是超过大小是会OOM的。

The following exceptional conditions are associated with native method stacks:

StackOverflowError
OutOfMemoryError

本地方法栈

执行本地方法,native方法属于C的方法。 (官方证明:An implementation of the Java Virtual Machine may use conventional stacks, colloquially called "C stacks," to support native methods (methods written in a language other than the Java programming language).)

程序计数器

因为在多线程的情况下,CPU通过轮询来去提高执行效率,线程之间会进行切换。如果从离开到下一次再进来,一定要知道上一次的一个状态。所以它应该是来干这件事情的。

(官方证明:The Java Virtual Machine can support many threads of execution at once (JLS §17). Each Java Virtual Machine thread has its own pc (program counter) register. )

总结

堆里面其实可以分为堆与非堆的概念。

方法区、堆的部分属于主内存,所有线程共享,是都可以访问。属于线程不安全。

虚拟机栈、本地方法栈、程序计数器,线程独有/私有,属于线程安全的部分。

参考地址

  • https://docs.oracle.com/javase/specs/jvms/se8/html/index.html
  • https://docs.oracle.com/javase/8/
原文  http://www.cyblogs.com/jvmshen-ru-li-jie-san-nei-cun-mo-xing/
正文到此结束
Loading...