Java8 的内存划分:https://blog.csdn.net/bruce128/article/details/79357870

运行时数据区域

线程私有:

  • 虚拟机栈
  • 本地方法栈
  • 程序计数器

线程共享:

  • 方法区(JDK8 已移除)

JDK 1.8:

image.png


1、程序计数器

指向当前线程正在执行的字节码的行号,如果当前执行的是 Nativate 方法,则为 null


2、Java 虚拟机栈

image.png
每调用一个方法,就会往虚拟机栈中创建一个栈帧

  • 栈帧:局部变量表、操作数栈、动态链接、方法出口信息
  • 局部变量表:局部变量(八大原始类型、对象引用)、returnAddress(方法返回地址)

3、本地方法栈

用于调用 Nativate 方法


4、堆

年轻代 Young Gen
Eden + Survivor * 2 = 8 : 1 : 1

老年代 Old Gen
Young Gen : Old Gen = 1 : 2

字符串常量池


5、方法区

Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但它并不在堆中,所以有别名 Non-Heap

存储被 JVM 加载的类信息常量静态变量即时编译器编译后的代码等数据。
所以,动态生成类的情况,容易造成永久代的溢出。比如 JSP

名称:

  • 方法区:JVM 规范
  • 永久代:JVM 规范的一种实现,JDK1.8 之前放在堆外的独立空间,在 GC 范围。
    • HotSpot 才有 PermGen space,其他虚拟机没有


常量池:**

  • 类文件中常量池(编译期):Class 文件中的常量池保存着各种编译期生成的各种字面量和符号引用
    • 字符串常量池(编译期):存放各种字符串常量
  • 运行时常量池(运行期):上述内存将在类加载后进入运行时常量池中存放
    • 具备动态性,存储翻译后的直接引用、运行期间的新常量(String.intern())
    • JDK1.7,从方法区迁移至

运行中常量池:JDK1.7 从方法区迁移至
永久代:JDK1.8 移除永久代,使用元空间 Metaspace 来实现方法区

  • PermSize 和 MaxPermGen 已经无效

元空间 Metaspace:

  • 元空间是对 JVM 规范中方法区的实现,使用 Native Memory
  • -XX:MetaspaceSize,初始空间大小
  • -XX:MaxMetaspaceSize,最大空间

Class 对象:堆

  • Class 对象是类加载地最终产物

类的方法代码、变量名、方法名、访问权限、返回值等:方法区

Class 文件中的常量池:
如果变量名和字符串的值一样,那么常量池中只会保留一份字面量:
image.png
javap -verbose xxx.class
image.png
String.intern():检查字符串常量池中是否存在String并返回池里的字符串引用;若池中不存在,则将其加入池中,并返回其引用。
这样做主要是为了避免在堆中不断地创建新的字符串对象