jvm学习笔记

虚拟机的前世今生和java内存区域

1.虚拟机的前世今生

.java文件编译成字节码.class文件,这样可以在jvm中运行,其中还需要借助jre里面已经定义好的java类库。

而jvm中又包含classloader、字节码解释器、jit编译器和执行引擎。

.class是字节码文件,jvm可以将很多语言转换成字节码文件,从而实现在多平台上运行(windows、linux、unix、andriod、mac)

1.1常见的jvm实现

  • hotspot-oracle
  • jrocket-oracle
  • j9-ibm
  • taobaovm-taobao(hotspot的深度定制版本)
  • liquidvm-bea
  • zing

1.2jvm的知识体系

  • 内存结构

    1.垃圾回收

    2.性能调优

    3.jvm自身优化技术

    4.执行引擎

    5.监控工具

    6.类文件结构

    7.类加载

2.jvm的内存区域

2.1运行时数据区域

  • 线程共享区
    • 方法区
      • 运行时常量池
  • 线程私有区
    • 虚拟机栈
    • 本地方法栈
    • 程序计数器
  • 直接内存
    • 总共8g内存,jvm占用3g,直接内存还剩5g

2.2虚拟机栈

  • 存储当前方法所需要的数据、指令、返回地址
    • 大小限制 -Xss,一般是1m,不同虚拟机不一样
    • 先进后出
    • 栈溢出,递归无出口时会造成栈溢出(stackOverFlowError)

2.3 方法区

  • 方法区用以将class里面的类加载到类加载器中

    • 类信息
    • 常量
  • 永久代(jdk1.7里面方法区的名称)和元空间(jdk1.8里面方法区的名称)。

  • 类加载

    • class文件需要解析,把变量放到常量池中

      • √运行时常量池()

        • class-- 符号引用 -》直接引用(真实的内存地址)

          {

          ​ Tool.hashcode(); ~13号

          }

      • 静态常量池(javap -c)

      • 字面量:String a = “b”;b就是字面量

  • 方法区是静态的,创建后经常使用的

2.4堆

  • 堆是保存对象的,是动态的,gc的主要区域。

2.5 直接内存(堆外内存)(EHcache)(中间件)

  • NIO中的DirectByteBuffer
  • 使用直接内存需要手动回收资源
  • unsafe类中allocateMemory方法可以分配内存

3.java方法的运行于虚拟机栈

3.1栈帧

  • 局部变量表(基础数据、引用对象的字段)(0是this)(iconst_1对应于1)(iconst_2对应2)
  • 操作数栈(重点)(执行引擎的一个工作区)(cpu+主内存+缓存)(jvm属于mini版本的操作系统)(对应的就是jvm执行引擎+堆、栈+操作数栈)(javap -v可以对class文件进行反汇编)(腾讯云java虚拟机 jvm字节码 指令集(https://cloud.tencent.com/developer/article/1333540))(iadd后为什么要入栈,因为cpu不会暂时保存数据,所以操作数栈起到了一种中间缓存的作用,在执行引擎中生成的中间数据全部保存到操作数栈中)(如果局部变量表中的数据要返回,必须先入栈,因为执行引擎只能与操作数栈交互)
  • 动态连接(需要结合class文件和执行引擎来讲)
  • 完成出口(返回地址)(class文件反汇编后,前面会有0、1、2、3、4、5…,这相当于c、c++中的偏移量,可以看出字节码的地址和行号)

3.2栈帧执行对内存区域的影响

  • 运行java方法,生成一个虚拟机栈,入一个栈帧,方法中如果调用其他方法,又会压入一个栈帧,其中包括局部变量表、操作数栈

  • 字节码指令iadd:将数据从操作数栈出栈,在执行引擎进行加法运算,然后自动入到操作数栈

  • 程序计数器(cpu要多核执行):字节码的行号,程序的反跳和异常跳出都需要程序计数器,

    • √操作系统:CPU时间片轮转机制。CPU1s中可以干10w个指令,因此将时间进行了切片,假设被切成了1000片,每一片不一定是连续的。
    • 程序计算器是操作系统中唯一不会oom的。因为它只是单纯的计数。

3.3 本地方法栈–加了native的方法

  • 在c/c++中实现,需要本地方法栈执行。
  • 虚拟机规范,因为虚拟机里面方法的执行有上面这样一套入栈出栈的思路,所以需要一套单独的同模式的框架来实现相同的处理。

答疑

1.一个线程只有一个程序计数器

2.iload_3入栈后,这个数值仍然存在于局部变量表中

3.时间片轮转,反汇编的行号为什么不连续?因为有的指令需要多个字节的操作数。(http://m.bubuko.com/infodetail-1884259.html?cf_chl_jschl_tk=02b6ebdd51151a04341cae188624d6b508e2fd50-1598025370-0-AQ9iU1GqGo4JaXQ6VtuLmtOTBaXABtUNjNZuiWWelzLE76-YHB2S8XH6gPsNdAF5ouLuc_jLHeTOPOEXDjWZVcE-valAYgC3obV4xMImrbdrbgfZYTt7b6YSO-66jkfIMHNzCX2g2gT4Dm-bhOkhMUKW0fr_XwxSRlWV6PxDV936EtFejh7R96GkQQfjyTefvyoRG9RMj-62heDsxSnte8ptJgOqEU0WT7OGqW-SgKuXPgSKBJCYk-yjJjWupRGGSImvXqBw-vYUMAshcvfsiQFDRik4O73YCmColjLTAyS_pIrae-sbN94jAEBLK8Bxsw)

4.运行时常量池中符号引用变为直接引用是什么意思?

5.栈溢出的主要原因是不断的压栈帧

6.栈帧出栈后不需要回收,这块区域就没有了,跟随线程销毁

7.ireturn到哪里?属于一个指令,根据返回值类型进行区分返回

8.不是操作数栈溢出,指令集设计有问题,是虚拟机栈溢出

9.符号引用,不指代地址,jvm运行后当变成直接引用,就代表了具体的地址。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值