Jvm基础(二)

2 篇文章 0 订阅
2 篇文章 0 订阅

目录

案列

runtime Data Area(运行时数据区)

Instructions(指令集)

常用指令


案列

public class JVM {
    public static void main(String[] args) {
        int i = 8;
        i = i++;
        System.out.println(i);
    }
}

请问最后答案是多少?

     


答案是8。

为什么呢?你看了这篇文章就了解个大概了。

runtime Data Area(运行时数据区)

运行时数据区是非常重要的一个执行区。


jvm 运行时的区域一共有这么几个区域

  • JVM stacks jvm栈 每个线程对应一个栈
    • Frame 栈帧 重点 每个方法对应一个栈帧
      • Local Variable table 本地局部变量表

注意:非static方法的LocalVariableTable里会有this

ps:这个是上一篇说到的Jclasslib idea的插件(方便开发者读取并分析内存的帮手)

Instructions(指令集)

  •                  Operand Stack 栈
 0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 <java/lang/System.out : Ljava/io/PrintStream;>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println : (I)V>
15 return

jvm会把class 方法解析成一个个字节码指令。每个指令对应的就是jvm的操作。

如果你不知道指令代表什么意思可以ctrl 点进去 会直接有对应的链接进去观看      右键会有一个show jvm spec 会直接跳到对应的地址

 分析:

第一步是压栈 把8放在栈里面

第二步是 把int值放在局部变量表 也就是LocalVariableTable里 的1位置

这两步完成的时候也就int i = 8 这个指令完成

第三步是 把局部变量表 1这个位置拿出来 压栈 也就是把i又拿进来了

第四步是 把局部变量表 1这个位置加1 所以 这时候局部变量表的i已经变成9了 但是栈里面是8

第五步是 和第二部一样 又把栈里的8 放在了1位置 也就是i覆盖了9

第六步也就是返回 所以就是8

      • Dynamic linking 动态链接 其实就是指向常量池的符号链接 其实就是A方法里 一个B方法 的链接 链接就是从常量池找
      • return address 返回地址 方法a调用方法b 如果有返回值,b方法的返回值放在什么地方

以上就是每个栈里面的东西

  • Program Counter 简称pc 指的是下一条指令位置 实际上特别小 每个线程都有自己的pc

虚拟机的运行,类似于一个循环

while(not end){

取pc的位置,找到对应位置的指令

执行该指令

PC++

}

  • Direct Memory 直接内存nio jdk1.4以后的内容 也就是可以直接访问操作系统内存的

不归jvm管 归os管 省了拷贝过程比io 0拷贝

  • native method stacks 本地方法 调用c c++ jni 一般不用去管
  • method area 方法区 装的是各种class 各种常量池的内容 所有线程共享 (重点)
    • Perm Space(<jdk1.8)永久区

字符串常量位于PermSpace

FGC不回收 bug

大小启动的时候指定,不能变

    • Meta Space(>=1.8) 元数据区

会触发FGC清理

字符串常量位于堆

不设定的话,最大就是物理内存

方式区是逻辑上的概念 具体的实现是Perm Space 和Meta Space是具体的实现

思考 如何证明1.7 位于perm 而1.8位于heap?

结合GC 一直创建字符串常量,观察堆和metaspace

  • Heap GC 重点中的重点 所有线程共享
  • run-time constant pool 常量池

注意:这里就是sipush 200 和之前讲的bipush 8 有点不一样 所以大家一定要自己ctrl点进去自己看 sipush 是因为已经超过了127 一个字节的大小(-128到127),所以才会默认转成short类型,还有其他类似于ldc,ldc2_w 也是。ldc是从常量池里拿数据压栈,所以这里是想说可以多去看看指令集的解释,比直接模仿印象更深刻,懂得也就更多。

 ​​​​​​​

补充:

基于栈的指令集 是jvm的 指令集

基于寄存器的指令集是os的指令集

hotspot 的local variable table 类似于寄存器

 

常用指令

store

load

pop

mul

sub

invoke

  • InvokeStatic
    • 调用静态的方法

InvokeVirtual

    • 多数的情况 new 一个东西 非静态的
  • InvokeInterface
    • 子类赋到父类的一个实现 List list = new ArrayList();
  • InovkeSpecial
    • 可以直接定位,不需要多态的方法,构造方法 和 private 网传final 方法不是的
  • InvokeDynamic
    • jvm最难的指令
    • 动态语言 lambda 表达式或者反射或者其他动态语言scala kotlin,或者CGLib ASM,动态产生的指令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值