Java 8 的内存结构

Java8内存结构图

虚拟机内存与本地内存的区别

Java虚拟机在执行的时候会把管理的内存分配成不同的区域,这些区域被称为虚拟机内存,同时,对于虚拟机没有直接管理的物理内存,也有一定的利用,这些被利用却不在虚拟机内存数据区的内存,我们称它为本地内存,这两种内存有一定的区别:

JVM内存

本地内存

java运行时数据区域

java虚拟机在执行过程中会将所管理的内存划分为不同的区域,有的随着线程产生和消失,有的随着java进程产生和消失。

程序计数器(Program Counter Register)

程序计数器就是当前线程所执行的字节码的行号指示器,通过改变计数器的值,来选取下一行指令,通过他来实现跳转、循环、恢复线程等功能。

虚拟机栈(JVM Stacks)

 虚拟机栈是线程私有的,随线程生灭。虚拟机栈描述的是线程中的方法的内存模型:

每个方法被执行的时候,都会在虚拟机栈中同步创建一个栈帧(stack frame)。

每个栈帧的包含如下的内容

  • 局部变量表

    • 局部变量表中存储着方法里的java基本数据类型(byte/boolean/char/int/long/double/float/short)以及对象的引用(注:这里的基本数据类型指的是方法内的局部变量)
  • 操作数栈

  • 动态连接

  • 方法返回地址

方法被执行时入栈,执行完后出栈

虚拟机栈可能会抛出两种异常:

本地方法栈(Native Method Stacks)

本地方法栈与虚拟机栈的作用是相似的,都会抛出OutOfMemoryError和StackOverFlowError,都是线程私有的,主要的区别在于:

  • 虚拟机栈执行的是java方法
  • 本地方法栈执行的是native方法

Java堆(Java Heap)

java堆是JVM内存中最大的一块,由所有线程共享,是由垃圾收集器管理的内存区域,主要存放对象实例,当然由于java虚拟机的发展,堆中也多了许多东西,现在主要有:

java堆既可以是固定大小的,也可以是可扩展的(通过参数-Xmx和-Xms设定),如果堆无法扩展或者无法分配内存时也会报OOM。

 

方法区(Method Area)

方法区是所有线程共享的内存,在java8以前是放在JVM内存中的,由永久代实现,受JVM内存大小参数的限制,在java8中移除了永久代的内容,方法区由元空间(Meta Space)实现,并直接放到了本地内存中,不受JVM参数的限制(当然,如果物理内存被占满了,方法区也会报OOM),并且将原来放在方法区的字符串常量池和静态变量都转移到了Java堆中,方法区与其他区域不同的地方在于,方法区在编译期间和类加载完成后的内容有少许不同,不过总的来说分为这两部分:

类元信息(Klass)

运行时常量池(Runtime Constant Pool)

直接内存

直接内存位于本地内存,不属于JVM内存,但是也会在物理内存耗尽的时候报OOM。

Native方法

由于java是一门高级语言,离硬件底层比较远,有时候无法操作底层的资源,于是,java添加了native关键字,被native关键字修饰的方法可以用其他语言重写,这样,我们就可以写一个本地方法,然后用C语言重写,这样来操作底层资源。当然,使用了native方法会导致系统的可移植性不高,这是需要注意的。

原文地址:https://www.cnblogs.com/KL2016/p/15495522.html