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的区别?

  1. Perm Space (<1.8)
    字符串常量位于PermSpace
    FGC不会清理
    大小启动的时候指定,不能变
  2. Meta Space (>=1.8)
    字符串常量位于堆
    会触发FGC清理
    不设定的话,最大就是物理内存

思考:
如何证明1.7字符串常量位于Perm,而1.8位于Heap?
提示:结合GC, 一直创建字符串常量,观察堆,和Metaspace

JVM从入门到精通(五): Java运行时数据区和常用指令相关推荐

  1. Java运行时数据区及对象的分配

    一.Java运行时数据区 简图: 简述: 堆.方法区是线程共享的,虚拟机栈.程序计数器.本地方法栈是线程私有的,一个线程一份. 虚拟机栈的基本单位是栈帧,一个方法的开始执行意味着一个栈帧进栈,一个方法 ...

  2. JVM(七) -- 内存与垃圾回收(二) -- 运行时数据区(四) -- Java堆

    运行时数据区最重要的内容,对应书中2.2.4节.3.8节. 位置: 1. 概述 一个java进程对应一个jvm虚拟机,也对应一个堆空间 一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域 ...

  3. 最全的 JVM 面试知识点(一):运行时数据区

    转自: https://blog.csdn.net/keets1992/article/details/92089754 不是码农,不会敲代码的她,却最懂程序员!| 人物志: https://blog ...

  4. Java虚拟机2:Java 运行时数据区

    前言快速到底 如果有人问你 java 的内存区域分为哪些,可能很多人会说:堆.栈.方法区--.我个人理解从开发者的角度 Java 能够涉及到"内存区域"的大致有两处:第一,java ...

  5. java多线程内存隔离_JVM之Java运行时数据区(线程隔离区)

    JVM会在会在执行Java程序过程中把所管理的内存划分为若干区域,主要包括程序计数器(Program Counter Register),虚拟机栈(VM Stack),本地方法栈(Native Met ...

  6. JVM(Java虚拟机模型、Java运行时数据区模型)

    一.Java代码运行原理 .java编译变成.class文件. 类加载器把.class字节码文件加载到JVM中. JVM中的字节码执行引擎从指定的main()方法开始执行代码. 二.类被加载的时机 代 ...

  7. 以独占方式锁定此配置文件失败.另一个正在运行_JVM深入解析:运行时数据区+HotSpot+JMM+堆+GC+JVM优化+类加载

    Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途.创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用 ...

  8. Java虚拟机运行时数据区

    将从<深入理解Java虚拟机:JVM高级特性与最佳实践>和 The Java® Virtual Machine Specification 中对于Java运行时数据区的描述整理记录一下 从 ...

  9. JVM运行时数据区概览

    在学习JVM之前我们需要明确的是,我们所学习的是JVM的一个规范,在实际中有很多不同种类的虚拟机来实现这一种规范.其次JVM运行时数据区和JMM的区别我们要搞清楚,不能将JMM理解为JVM运行是数据区 ...

最新文章

  1. 深度学习经典数据集汇总
  2. imutils用法总结
  3. UVA 10601 Cubes
  4. nginx linux 下载安装,Linux(CentOS)下载安装Nginx并配置
  5. TensorFlow使用--MNIST分类学习入门(感知机)
  6. 21天学通python-21天学通Python(第2版)_PDF电子书
  7. 2022年前端面试宝典【1万字带答案】
  8. 学习有法,事半功倍 — 在线学习的10个技巧
  9. 游轮旅游是三亚旅游的未来
  10. Linux下Valgrind的使用概述 来源:Linux社区 作者:dndxhej
  11. 阿里六面(总结他人事迹)
  12. 基于51单片机数码管显示
  13. linux 网络错误代码,Linux版本登录提示网络错误
  14. 用python给pdf批量添加水印,并给pdf加密
  15. Win11怎么减少笔记本耗电?解决Win11耗电快的方法
  16. Python实现图像的全景拼接,这不比ps牛逼
  17. Saliency Integration :An Arbitrator Model阅读总结
  18. android 4.4 batteryservice 电池电量显示分析
  19. ai如何旋转画布_Illustrator让一个图形沿着某一点或顶点旋转复制教程
  20. 有没有这样的后浪,月薪3000

热门文章

  1. PyTorch-混合精度训练
  2. C,C++中使用可变参数
  3. C语言程序设计 | 操作符介绍与使用方法
  4. frida 安装特定版本
  5. Python中re.sub()实现替换文本字符串
  6. nginx如何开启debug日志及相关配置
  7. 这里有一份面筋请查收(六)
  8. 剑指offer--剪绳子
  9. LiveVideoStack线上分享第三季(十一):Xilinx视频解决方案
  10. AOM联盟:AV1完成1.0版定稿