JVM -- Java内存区域HotSpot虚拟机对象探秘对象的访问定位的两种方式(句柄和直接指针两种方式)

Posted CodeJiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM -- Java内存区域HotSpot虚拟机对象探秘对象的访问定位的两种方式(句柄和直接指针两种方式)相关的知识,希望对你有一定的参考价值。

文章目录

1. Java 内存区域(运行时数据区)

Java 虚拟机在执⾏ Java 程序的过程中会把它管理的内存划分成若⼲个不同的数据区域。JDK. 1.8 和之前的版本略有不同。


1.1 JDK 1.8之前


1.2 JDK 1.8 以及之后


1.3 线程私有和共享

线程私有的:

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

线程共享的:

  • ⽅法区
  • 直接内存(⾮运⾏时数据区的⼀部分)

1.4 程序计数器

从上⾯的介绍中我们知道程序计数器主要有两个作⽤:

  1. 字节码解释器通过改变程序计数器来依次读取指令,从⽽实现代码的流程控制,如:顺序执⾏、选择、循环、异常处理。
  2. 在多线程的情况下,程序计数器⽤于记录当前线程执⾏的位置,从⽽当线程被切换回来的时候能够知道该线程上次运⾏到哪⼉了。

注意:程序计数器是唯⼀⼀个不会出现 OutOfMemoryError 的内存区域,它的⽣命周期随着线程的创建⽽创建,随着线程的结束⽽死亡。


1.5 Java 虚拟机栈

扩展:那么⽅法 / 函数如何调⽤?


1.6 本地方法栈

查看Java虚拟机类型:java -version


1.7 堆(堆内存中对象的分配的基本策略)

另外,⼤对象和⻓期存活的对象会直接进⼊⽼年代。

补充:



上图所示的 Eden 区、两个 Survivor 区都属于新生代(为了区分,这两个 Survivor 区域按照顺序被命名为 fromto),中间一层属于老年代。


1.8 方法区


1.8.1 方法区概念


1.8.2 方法区和永久代的关系

《Java虚拟机规范》只是规定了有⽅法区这么个概念和它的作⽤,并没有规定如何去实现它。那么,在不同的 JVM 上⽅法区的实现肯定是不同的了。 ⽅法区和永久代的关系很像Java中接⼝和类的关系,类实现了接⼝,⽽永久代就是HotSpot虚拟机对虚拟机规范中⽅法区的⼀种实现⽅式。 也就是说,永久代是HotSpot的概念,⽅法区是Java虚拟机规范中的定义,是⼀种规范,而永久代是⼀种实现,⼀个是标准⼀个是实现,其他的虚拟机实现并没有永久带这⼀说法


1.8.3 常用参数

JDK 1.8 之前:

JDK 1.8 之前永久代还没被彻底移除的时候通常通过下⾯这些参数来调节⽅法区⼤⼩

-XX:PermSize=N //⽅法区(永久代)初始⼤⼩
-XX:MaxPermSize=N //⽅法区(永久代)最⼤⼤⼩,超过这个值将会抛出OutOfMemoryError异常:java.lang.OutOfMemoryError: PermGen

相对而言,垃圾收集⾏为在这个区域是比较少出现的,但并⾮数据进⼊⽅法区后就“永久存在”了。

JDK 1.8 以及之后:

JDK 1.8 的时候,⽅法区(HotSpot的永久代)被彻底移除了,取⽽代之是元空间,元空间使⽤的是直接内存。

下⾯是⼀些常⽤参数:

-XX:MetaspaceSize=N //设置Metaspace的初始(和最⼩⼤⼩)
-XX:MaxMetaspaceSize=N //设置Metaspace的最⼤⼤⼩

与永久代很⼤的不同就是,如果不指定⼤⼩的话,随着更多类的创建,虚拟机会耗尽所有可⽤的系统内存


1.8.4 为什么要将永久代(PermGen)替换为元空间(MetaSpace)呢?

-XX:MaxMetaspaceSize
-XX:MetaspaceSize


1.8.5 运行时常量池


1.8.6 直接内存


2. HotSpot虚拟机对象探秘

通过上面的介绍我们大概知道了虚拟机的内存情况,下面我们来详细的了解一下 HotSpot 虚拟机在 Java 堆中对象分配、布局和访问的全过程。


2.1 对象的创建过程


2.1.1 类加载检查


2.1.2 分配内存

内存分配的两种方式:(补充内容,需要掌握)


内存分配并发问题(补充内容,需要掌握)


2.1.3 初始化零值


2.1.4 设置对象头


2.1.5 执行init方法


3.2 对象的内存布局


3.3 对象的访问定位

建立对象就是为了使用对象,我们的 Java 程序通过栈上的 reference 数据来操作堆上的具体对象。对象的访问方式由虚拟机实现而定,目前主流的访问方式有①使用句柄和②直接指针两种:

这两种对象访问方式各有优势。使用句柄来访问的最大好处是 reference 中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而 reference 本身不需要修改。使用直接指针访问方式最大的好处就是速度快,它节省了一次指针定位的时间开销。

句柄方式:

直接指针方式:



以上是关于JVM -- Java内存区域HotSpot虚拟机对象探秘对象的访问定位的两种方式(句柄和直接指针两种方式)的主要内容,如果未能解决你的问题,请参考以下文章

JVM -- Java内存区域HotSpot虚拟机对象探秘对象的访问定位的两种方式(句柄和直接指针两种方式)

JVM虚拟机内存

JVM考点整理1

Java虚拟机:JVM内存分代策略

JVM系列之七:HotSpot 虚拟机

JVM 学习总结