深入理解jvm-内存结构

本文参考圣思园张龙深入理解jvm

 

 

内存结构

虚拟机栈:Stack Frame 栈帧。虚拟机栈和线程的生命周期相同,伴随线程的诞生和结束,栈帧存储与线程相关的操作和数据。

注:引用类型不是对象,引用类型放在栈帧的局部变量表里。局部变量表里存放8个原生类型和对象引用类型(reference),reference可以直接指向堆中的对象,也可以通过句柄的方式(句柄:元信息,对象信息)。

程序计数器 (Program Counter):表示当前执行线程的行号或者顺序。

本地方法栈:主要用于处理/执行本地方放。(Hotspot就把本地方放栈和虚拟机栈合二为一了)。

堆(Heap)*:jvm管理的最大块内存空间。被所有线程所共享。与其重要相关的概念是垃圾收集器。现代几乎所有垃圾收集器都采用分代收集算法,所以堆空间也基于这一点进行划分。新生代和老年代。Eden空间,From Survivor与To Survivor 空间。老年代回收频率比新生代低很多。Java的堆空间在物理内存上即可以是连续的,也可以是非连续的。

方法区(Method Area):存储元信息 。永久代(Permanent Generation),从jdk1.8开始,已经彻底废弃了永久代,使用元空间(meta space)。存放如关于Class类对象的一些信息。很少被回收,如关于Class的卸载。

运行时的常量池:方法区的一部分内容。在Class的字节码中的常量池里,

直接内存:Direct Memory 堆外内存。不是由jvm直接管理的区域,与java NIO密切相关的。Jvm通过堆上的DirectByBuffer来直接操作内存。

深入理解jvm-内存结构

深入理解jvm-内存结构

 

内存分配原理和布局

关于java对象创建的过程。 New关键字创建对象的3个步骤:

  1. 在堆内存中创建出对象的实例。
  2. 为对象的实例成员变量赋初值。
  3. 将对象的引用返回

指针碰撞:前提是堆中的空间通过一个指针进行分割 一侧是已经被占用的空间,另一次未被占用。当未被占用空间放入一个新创建的对象之后,指针会发生偏移。

空闲列表:前提是堆内存空间中已被使用与未被使用的空间是交织在一起的,这时,jvm就需要通过一个列表来表示哪些空间时可以使用的,哪些空间时已经被使用的,接下来找出可以容纳下新创建对象的且未被使用的空间,在此空间存放该对象,同时还要修改列表上的记录。

 

对象在内存中的布局:1.对象头,2.实例数据(在一个类中所声明的各类信息)。3.对齐填充(可选,占位符)

 

引用访问对象的方式:1.句柄方式。2.使用直接指针的方式。

 

例子:在程序中,设置参数,最小内存和最大内存都为5M,并将堆内的信息打印到磁盘

深入理解jvm-内存结构

深入理解jvm-内存结构

内存分析工具Jvisualvm

 

深入理解jvm-内存结构

设置堆栈的大小

 

文章《Java 永久代去哪儿了》

https://www.infoq.cn/article/Java-PERMGEN-Removed/