Java 内存区域

运行时数据区域

程序计数器

线程所执行的字节码行号指示器。
唯一没有规定OutOfMemoryError的区域

java虚拟机栈

为虚拟机的Native方法创建的栈针,用于存储局部变量表,操作数帧,动态链接,方法出口信息

本地方法栈

为自己定义的Java方法进行服务

java堆

目的:存放实例,在这里分配内存 1.7之后常量池也在这里
1/3 年轻代 1/10 to Servivor 1/10 from Servivor 8/10 Eden
2/3 老年代

  • 方法区

各个线程共享的内存区域,存储加载的类信息,常量,静态变量,即时编译器编译后的代码等
“永久代”:并不是永久存在,只是回收效率低,容易发生内存泄露

  • 常量池

类的 版本,字段,方法,接口等描述信息,在运行过程中也可能会加入新的常量。
new String都是在堆上创建字符串对象。当调用 intern() 方法时,编译器会将字符串添加到常量池中(stringTable维护),并返回指向该常量的引用。 通过字面量赋值创建字符串(如:String str=”twm”)时,会先在常量池中查找是否存在相同的字符串,若存在,则将栈中的引用直接指向该字符串;若不存在,将在堆上的地址引用复制到常量池。
引号声明的字符串都是会直接在字符串常量池中生成的,而 new 出来的 String 对象是放在堆空间中的。所以两者的内存地址肯定是不相同的,

直接内存

不受Java堆的限制,可以用Native函数库直接操作分配堆外内存,并对其进行操作。

对象创建

1.指针碰撞 Serial、PraNew等存在将空间压实的回收器
2.空闲列表 CMS

一个对象的组成

对象头

1.自身运行时的数据【长度 32bit/32位虚拟机 OR 64bit/64位虚拟机】
HashCode
GC分代年龄
锁状态标志
线程持有的锁
偏向线程id
偏向时间戳
2.类型指针
ps:数组的大小信息也放在这里。所以普通JAVA对象可以通过元信息知道对象大小,但是数组不行,在元信息中没有该大小信息,需要在对象头里查看

实例数据

真实数据的地方。父类的变量出现于子类之前

对齐填充

占位符的作用

image.png

你可能感兴趣的:(Java 内存区域)