JVM从入门到精通(五): Java运行时数据区和常用指令
JVM Runtime Data Area and JVM Instructions
Java运行时数据区以及JVM指令
i=i++
结果为8
i=++i
结果为9
一个class的生命周期
以下面的规范为准:
运行时数据区的构成
PC:peogram counter 程序计数器
DirectMemory:直接内存,JVM可以直接访问内核空间的内存(OS管理的内存),零拷贝(不需要拷贝),NIO用到了,提高效率
MethodArea:方法区,里面有常量池
PC 程序计数器
JVM 栈空间
在每一个线程创建的时候,线程会有自己独立的JVM栈空间,栈中存放的是栈帧
堆空间
所有线程共享同一个堆空间。
堆空间是用来存放所有类实例和数组空间分配的运行时数据区。
方法区
所有线程共享同一个方法区。
方法区用来存放 per-class structors
Perm Space 与 Meta Space容易混淆,他们只是Method Area的两的不同版本的实现。
运行时常量池
栈帧
- 局部变量
- 操作数栈
- 动态链接
指向运行时常量池里面的符号链接,看有没有解析,如果没有解析,就动态解析,如果已经解析了,就拿过来使用。例如,A方法要调用B方法,B方法在哪儿呢?就要去常量池里面找。 - 返回值地址
A方法调用了B方法,如果有返回值,要记录返回值返回到那个地方,也就是记录继续执行的位置。
回到面试题
- 理解局部变量表
- 理解操作数栈
- 理解一些常用的指令
package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet;public class TestIPulsPlus {public static void main(String[] args) {int i = 8;i = i++;
// i = ++i;System.out.println(i);}
}
i=i++ 生成的指令
执行过程分析
i=++i 生成的指令
下面这个 i 因为超过了 127,所以用的是sipush,而不是上图中的bipush
为什么我们可以在非static方法中使用this?因为this在局部变量表中是已经存在的。
(局部变量表中,0位置是this,1位置是k,2位置是i)
下面这个例子,之前有一道面试题:DCL 单例为什么要加 volitile?因为你看下面的第一条指令,我们知道,刚new出来对象是半初始化的对象,只是赋一个默认值,而involespecial才是调用构造方法,给变量赋初始值,而这两条指令之间是可能会发生指令重排的。
返回值
递归的调用
下面是m方法的执行,没有把main方法放上来
在这个3层递归中,使用到的是3个栈
另外,我们看到指令前面的数字 0,1,2,5,6,…,没有3,4的原因,是2指令的字节数比较多,占用了后面的字节数
总结
invokeXXX指令
invokestatic
调用一个静态方法
invokevirtual
new一个对象,调用一个非静态方法
自带多态:new 的是哪个对象,调用的就是哪个对象的方法
invokespecial
调用实例方法;对超类、私有和实例初始化方法调用的特殊处理
可以直接定位的,不需要多态的方法
- private方法
- 构造方法
final方法不是invokespecial的,它是invokevirtual的。
invokeinterface
调用接口方法
invokedynamic
JVM最难的指令
invokedynamic是lambda表达式或者反射或者其他动态语言scala kotlin,或者CGLib ASM,动态产生的class,会用到的指令
每一个lambda表达式都有一个自己的内部类,java没有纯粹的函数。匿名内部类每次都是动态产生的。
package com.mashibing.jvm.c4_RuntimeDataAreaAndInstructionSet;public class T05_InvokeDynamic {public static void main(String[] args) {I i = C::n;I i2 = C::n;I i3 = C::n;I i4 = () -> {C.n();};System.out.println(i.getClass());System.out.println(i2.getClass());System.out.println(i3.getClass());for(;;) {I j = C::n;} //MethodArea <1.8 Perm Space (FGC不回收)}@FunctionalInterfacepublic interface I {void m();}public static class C {static void n() {System.out.println("hello");}}
}
关于Lambda表达式的一个坑
如果你用Lambda表达式写出了这样的代码:
for(;;) {I j = C::n;} //MethodArea <1.8 Perm Space (FGC不回收)
在1.8之前有一个巨大的bug,就是你在里面产生了很多对象,但是Perm Space在FGC的时候是不会回收的。
Perm Space和Meta Space的区别?
- Perm Space (<1.8)
字符串常量位于PermSpace
FGC不会清理
大小启动的时候指定,不能变 - Meta Space (>=1.8)
字符串常量位于堆
会触发FGC清理
不设定的话,最大就是物理内存
思考:
如何证明1.7字符串常量位于Perm,而1.8位于Heap?
提示:结合GC, 一直创建字符串常量,观察堆,和Metaspace
JVM从入门到精通(五): Java运行时数据区和常用指令相关推荐
- Java运行时数据区及对象的分配
一.Java运行时数据区 简图: 简述: 堆.方法区是线程共享的,虚拟机栈.程序计数器.本地方法栈是线程私有的,一个线程一份. 虚拟机栈的基本单位是栈帧,一个方法的开始执行意味着一个栈帧进栈,一个方法 ...
- JVM(七) -- 内存与垃圾回收(二) -- 运行时数据区(四) -- Java堆
运行时数据区最重要的内容,对应书中2.2.4节.3.8节. 位置: 1. 概述 一个java进程对应一个jvm虚拟机,也对应一个堆空间 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域 ...
- 最全的 JVM 面试知识点(一):运行时数据区
转自: https://blog.csdn.net/keets1992/article/details/92089754 不是码农,不会敲代码的她,却最懂程序员!| 人物志: https://blog ...
- Java虚拟机2:Java 运行时数据区
前言快速到底 如果有人问你 java 的内存区域分为哪些,可能很多人会说:堆.栈.方法区--.我个人理解从开发者的角度 Java 能够涉及到"内存区域"的大致有两处:第一,java ...
- java多线程内存隔离_JVM之Java运行时数据区(线程隔离区)
JVM会在会在执行Java程序过程中把所管理的内存划分为若干区域,主要包括程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native Met ...
- JVM(Java虚拟机模型、Java运行时数据区模型)
一.Java代码运行原理 .java编译变成.class文件. 类加载器把.class字节码文件加载到JVM中. JVM中的字节码执行引擎从指定的main()方法开始执行代码. 二.类被加载的时机 代 ...
- 以独占方式锁定此配置文件失败.另一个正在运行_JVM深入解析:运行时数据区+HotSpot+JMM+堆+GC+JVM优化+类加载
Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途.创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用 ...
- Java虚拟机运行时数据区
将从<深入理解Java虚拟机:JVM高级特性与最佳实践>和 The Java® Virtual Machine Specification 中对于Java运行时数据区的描述整理记录一下 从 ...
- JVM运行时数据区概览
在学习JVM之前我们需要明确的是,我们所学习的是JVM的一个规范,在实际中有很多不同种类的虚拟机来实现这一种规范.其次JVM运行时数据区和JMM的区别我们要搞清楚,不能将JMM理解为JVM运行是数据区 ...
最新文章
- 深度学习经典数据集汇总
- imutils用法总结
- UVA 10601 Cubes
- nginx linux 下载安装,Linux(CentOS)下载安装Nginx并配置
- TensorFlow使用--MNIST分类学习入门(感知机)
- 21天学通python-21天学通Python(第2版)_PDF电子书
- 2022年前端面试宝典【1万字带答案】
- 学习有法,事半功倍 — 在线学习的10个技巧
- 游轮旅游是三亚旅游的未来
- Linux下Valgrind的使用概述 来源:Linux社区 作者:dndxhej
- 阿里六面(总结他人事迹)
- 基于51单片机数码管显示
- linux 网络错误代码,Linux版本登录提示网络错误
- 用python给pdf批量添加水印,并给pdf加密
- Win11怎么减少笔记本耗电?解决Win11耗电快的方法
- Python实现图像的全景拼接,这不比ps牛逼
- Saliency Integration :An Arbitrator Model阅读总结
- android 4.4 batteryservice 电池电量显示分析
- ai如何旋转画布_Illustrator让一个图形沿着某一点或顶点旋转复制教程
- 有没有这样的后浪,月薪3000