Java内存分配

第一,程序计数器(PC,Program Counter Register)。在 JVM 规范中,每个线程都有它自
己的程序计数器,并且任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序
计数器会存储当前线程正在执行的 Java 方法的 JVM 指令地址;或者,如果是在执行本地方
法,则是未指定值(undefined)。
第二,Java 虚拟机栈(Java Virtual Machine Stack),早期也叫 Java 栈。每个线程在创建时
都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的 Java 方
法调用。
前面谈程序计数器时,提到了当前方法;同理,在一个时间点,对应的只会有一个活动的栈帧,
通常叫作当前帧,方法所在的类叫作当前类。如果在该方法中调用了其他方法,对应的新的栈帧
会被创建出来,成为新的当前帧,一直到它返回结果或者执行结束。JVM 直接对 Java 栈的操作
只有两个,就是对栈帧的压栈和出栈。
栈帧中存储着局部变量表、操作数(operand)栈、动态链接、方法正常退出或者异常退出的定
义等。
第三,(Heap),它是 Java 内存管理的核心区域,用来放置 Java 对象实例,几乎所有创建
的 Java 对象实例都是被直接分配在堆上。堆被所有的线程共享,在虚拟机启动时,我们指定
的“Xmx”之类参数就是用来指定最大堆空间等指标。
理所当然,堆也是垃圾收集器重点照顾的区域,所以堆内空间还会被不同的垃圾收集器进行进一
步的细分,最有名的就是新生代、老年代的划分。
第四,方法区(Method Area)。这也是所有线程共享的一块内存区域,用于存储所谓的元
(Meta)数据,例如类结构信息,以及对应的运行时常量池、字段、方法代码等。
由于早期的 Hotspot JVM 实现,很多人习惯于将方法区称为永久代(Permanent
Generation)。Oracle JDK 8 中将永久代移除,同时增加了元数据区(Metaspace)。
第五,运行时常量池(Run-Time Constant Pool),这是方法区的一部分。如果仔细分析过反
编译的类文件结构,你能看到版本号、字段、方法、超类、接口等各种信息,还有一项信息就是
常量池。Java 的常量池可以存放各种常量信息,不管是编译期生成的各种字面量,还是需要在
运行时决定的符号引用,所以它比一般语言的符号表存储的信息更加宽泛。
第六,本地方法栈(Native Method Stack)。它和 Java 虚拟机栈是非常相似的,支持对本地
方法的调用,也是每个线程都会创建一个。在 Oracle Hotspot JVM 中,本地方法栈和 Java 虚
拟机栈是在同一块儿区域,这完全取决于技术实现的决定,并未在规范中强制。

你可能感兴趣的:(JAVA)