Java内存结构

一、介绍

  Java 的内存结构可以从两个方面来讲:内存模型和内存区域。

  内存模型:即 JMM,内存模型是抽象线程和主内存的抽象关系,即JVM在计算机内存(RAM)中的工作方式,在研究多线程时,JMM需要深入理解

  内存区域:即JVM 在程序运行时对内存的划分(强调内存划分)

二、JVM内存区域

 

 上图时 JVM 运行时对整体架构,其中中间部分是 JVM 运行时对内存区域划分,很明显的看到:

1、线程私有的一些区域:程序计数器、本地方法栈、虚拟机栈

2、线程公有的一些区域:方法区、堆、另外还有堆外内存(元空间等)

 

1、程序计数器

   程序计数器是线程所私有的,主要的作用就是用来标识当前线程执行到的位置(标志执行到字节码的位置),如:在需要恢复当前线程重新执行就需要用到这个程序计数器,程序控制循环分支、跳转、异常处理也需要用到程序计数器。

2、虚拟机栈

  每个线程在创建的时候,都会创建一个虚拟机栈,这个栈是线程私有的,线程每一次调用方法都会存入这个栈,且各个方法之间的数据传递也是通过这个栈进行传递,里面的每一个栈帧的组成大概是:局部变量表、操作数栈、动态链接、方法出口信息等。其生命周期与线程一致。

 

 

 

 

3、本地方法栈

  与虚拟机栈的作用十分类似,区别是虚拟机栈是为Java方法服务,即字节码,而本地方法栈主要是为Native方法服务

  本地方法可以通过本地方法接口来访问虚拟机内部的运行时数据区,它甚至可以直接使用本地处理器中的寄存器,直接从本地内存的堆中分配任意数量的内存

4、堆内存

  Java堆是虚拟机所管理的内存中最大的一块区域,是所有线程所共享的一块内存区域,Java世界里几乎所有的对象实例都在这里分配内存,但随着Java语言的发展,在堆里分配内存也不是那么绝对。

  Java堆是垃圾回收器管理的区域,所以也成为 “GC堆”,所以为了进行高效的垃圾回收,Java堆被逻辑上划分成三部分:

  • 新生代:即刚申请的一些内存空间
  • 老年代:即申请过了很久还在被使用的内存空间
  • 元空间(JDK8之前叫永久代):像一些方法中的操作临时对象等,JDK1.8 之前是占用 JVM 内存,JDK1.8 之后直接使用物理内存

 

 

  堆内存的划分如上图所示:其中 Eden、S0、S1都属于新生代,而Old Memory 属于老年代,Perm属于永久代。

  默认情况下,新申请的内存都会在 Eden 内,如果在经历一次垃圾回收后,没有被清理的内存的年龄就会 +1 ,就会进入 S1或者S0,而随着年龄的增长,如果年龄超过阙值,就会进入老年代,这个阙值是 GC 遍历完整个内存后,年龄超过一半以上的内存,则会进去老年代,这个一半的年龄就是阙值。

5、方法区

  方法区同样是所有线程共享的内存区域,它用于存储已经被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。

 

方法区 和 元空间 的区别:

 

 永久代和元空间都可以理解为方法区的落地实现,永久代是堆的一部分,属于虚拟机内存(受 GC 管理),而元空间则是本机内存。

6、运行时常量池

  运行时常量是方法区的一部分,Class 文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译期生成的各种字面量和符号引用,这部分将在类加载后存放到方法区的运行时常量池中。

  为什么需要常量池?

  一个 Java 源文件中的类、接口,编译后产生一个字节码文件。而 Java 中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。在动态链接的时候用到的就是运行时常量池。
 
  • 在加载类和结构到虚拟机后,就会创建对应的运行时常量池
  • 常量池表(Constant Pool Table)是 Class 文件的一部分,用于存储编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中
  • JVM 为每个已加载的类型(类或接口)都维护一个常量池。池中的数据项像数组项一样,是通过索引访问的
  • 运行时常量池中包含各种不同的常量,包括编译器就已经明确的数值字面量,也包括到运行期解析后才能够获得的方法或字段引用。此时不再是常量池中的符号地址了,这里换为真实地址
    • 运行时常量池,相对于 Class 文件常量池的另一个重要特征是:动态性,Java 语言并不要求常量一定只有编译期间才能产生,运行期间也可以将新的常量放入池中,String 类的 intern() 方法就是这样的
  • 当创建类或接口的运行时常量池时,如果构造运行时常量池所需的内存空间超过了方法区所能提供的最大值,则 JVM 会抛出 OutOfMemoryError 异常

三、Java内存模型

 

posted @ 2022-04-16 18:45  空心小木头  阅读(960)  评论(0编辑  收藏  举报