快速了解JVM

jvm跨平台原理

不同的操作系统上运行的jvm是不同的,但是功能,作用是相同的,所以只要将Java代码编译成字节码,各个操作系统的jvm都能将他执行成相同的效果。

字节码的作用是什么

hello.java----javac---->hello.class-----执行—>JVM

java代码-----编译----->字节码-----解释----->机器指令
作用:兼容各种语言,供不同平台的JVM解释成相应的机器指令

JVM整体结构

  1. hello.java
  2. hello.class
  3. 类加载子系统(类加载器)
  • 加载
  • 链接
    • 验证:验证待加载class文件是否正确,比如验证,比如验证文件格式
    • 准备:为static变量分配内存并赋零值
    • 将符号引用解析为直接引用
  • 初始化
  1. 运行时数据区(Runtime Data Area)
  • 本地方法栈(native方法)
  • Java方法栈(Java方法)
  • 方法区
  • 程序计数器(执行指令时,线程切换后又继续执行应该从哪一条指令继续执行)
  1. 执行引擎
  • 解释器
  • JIT编译器
  • 垃圾回收器

类加载器的分类

  • 引导类加载器:BootStrapClassLoader
    加载jre/lib目录下的包或类
  • 自定义类加载器:继承实现ClassLoader类
    • ExtClassLoader(扩展类加载器)
      加载jre/lib/ext目录下的包或类
    • AppClassLoader
      加载classpath路径下的包和类
    • WebAppClassLoader

双亲委派(向上委派)

AppClassLoader------>ExtClassLoader------->BootStrapClassLoader
作用:

  • 避免类的重复加载
  • 防止核心API被篡改

Tomcat里面为什么要自定义类加载器

为了实现类加载的隔离
eg:
应用A和应用B存在类名相同的类(内容不同)需要被加载,但AppClassLoader只有一个,不能创建多个,所以有可能只能加载一个,在JVM中判断一个类是否已经被加载的逻辑是:类名+对应的类加载器实例,所以Tomcat自定义类加载器的原因是实现类加载的隔离。

运行时数据区

  • 方法区(多线程共享):常量池,方法信息,类信息
  • 堆(多线程共享):
    • 新生代
      • Eden
      • S0
      • S1
    • 老年代
  • java方法栈(线程私有):
    • 栈帧:
      • 局部变量表
      • 操作数栈
      • 动态链接
      • 方法返回地址
  • 本地方法栈(线程私有):native本地方法相关信息
  • 程序计数器(线程私有):记录当前程序下一条执行的指令

程序计数器(PC Register)

  1. 是物理寄存器的抽象实现
  2. 用来记录待执行的下一条指令的地址
  3. 它是程序控制流的指示器,循环、if else、异常处理、线程恢复等都依赖它来完成
  4. 解释器工作时就是通过它来获取下一条需要执行的字节码指令的
  5. 它是唯一一个在JVM规范中没有规定任何OutOfMemoryError(内存溢出)情况的区域

虚拟机栈(Java栈,Java方法栈)

每个线程在创建时都会创建一个虚拟机栈,栈内会保存一个个的栈帧,每个栈帧对应一个方法。

  1. 虚拟机栈是线程私有的
  2. 一个方法开始执行栈帧入栈,方法执行完对应的栈就出栈,所以虚拟机栈不需要进行垃圾回收
  3. 虚拟机栈存在OutOfMemoryError和StackOverflowError
  4. 线程太多就有可能出现内存溢出,现车给创建时没有足够的内存去创建虚拟机栈了
  5. 方法调用层次太多,就可能会出现栈溢出
  6. 可以通过***-Xss***来设置虚拟机栈的大小

栈帧

  • 局部变量表(多个slot)
    记录局部变量在局部变量表中的位置和值
  • 方法返回地址
  • 操作数栈
    用来在执行字节码指令过程中用来进行计算,
  • 动态链接
  • 附加信息

本地方法栈

本地方法:native method,在Java中定义的方法,但由其他语言实现

虚拟机栈存的是Java方法调用过程的栈帧,本地方法栈存的是本地方法调用过程中的栈帧。是线程私有的,可能会出现内存溢出和栈溢出。

-Xms:ms(memory start),指定堆的初始化内存大小,等价于-XX:initailHeapSize

-Xmx:mx(memory max),指定堆的最大内存大小,等价于-XX:MaxHeapSize

一般情况下会把ms和mx设置为一样大,这样JVM就不需要在GC后去修改堆的内存大小了,提高了效率,默认情况下,初始化内存大小=物理内存大小/64,最大内存大小=物理内存大小/4

可以通过-XX:NewRatio参数来配置新生代和老年代的比例,默认为2,表示新生代占1,老年代占2,也就是新生代占堆区总大小的1/3.

新生代中的eden,s0,s1的比例关系为8:1:1,可以通过-XX:SurvivorRatio来调整

新生对象创建后都会先存在eden区,当eden区满了就会触发MinorGC或YGC机制,回收一些垃圾对象,剩下的就会存入到S0区,并记录这些对象都经历过几次GC(YGC),后续eden区又满了,又会回收,然后eden转S0,S0剩下的转S1并记录2,表示这些对象经历过两次GC了,后面不断重复这个过程,当对象经历过的GC次数变成15时,下次再次执行时就会被放入老年代 ,当eden里面放了一个大对象时,S0,S1放不下就有可能从Eden直接到老年代,还有一种可能是Eden区都放不下的超大对象有可能直接放入老年代。

垃圾回收:

  • Young GC/Minor GC:负责新生代的垃圾回收
  • Old GC/Major GC:老年代垃圾回收
  • Full GC:整堆回收

为什么要进行垃圾回收

垃圾是指在JVM中没有任何引用指向它的对象,如果不清理这些垃圾对象,它们就会一直占着内存,而不能给其他对象使用,最终垃圾对象越来越多,就会出现内存溢出(OOM)了。

垃圾标记阶段

  • 引用计数法
    每个对象都保存一个引用计数器属性,用于记录对象被引用的次数。
    优点:实现简单,计数器为0时就代表是垃圾对象
    缺点:需要额外空间存储引用和维护计数器,无法处理循环引用的问题
  • 可达性分析法
    以GC root(栈或方法区中存在的对象引用)为起始点,然后一层一层的找到所引用的对象,被找到的对象就是存活的对象,那么其他不可达对象就是垃圾对象。

标记清除算法

如果内存不足后,就会STW,暂停用户线程的执行,然后执行算法进行垃圾回收

  1. 标记阶段:从GC root开始遍历,找到可达对象,并在对象头中进行记录
  2. 清除阶段:堆内存空间进行线性遍历,如果发现对象头中没有记录是可达对象,则回收它

复制算法

将内存空间分为两块,每次只使用一块,在进行垃圾回收时,将可达对象复制到另外没有被使用的内存块中,然后再清除当前内存块中的所有对象,后续再按照同样的流程来进行垃圾回收,交换着来。

优点:

  • 没有标记和清除阶段,通过GC root找到可达对象,直接复制,不需要修改对象头,效率高,不会出现内存碎片

缺点:

  • 需要更多的内存,始终有一半内存空闲
  • 如果可达对象比较多,那么复制过程中的开销就较大了
  • 对象复制后,对象的内存地址发生了变化,需要修改维护引用地址

标记整理法

第一阶段和标记清除法一样,从GC root中找到并标记可达对象
第二阶段将所有存活对象移到内存的另一端
最后清理掉边界外所有的空间

垃圾清除算法对比总结:

标记-清除标记-整理复制
速度中等最慢最快
空间开销少(有碎片)少(无碎片)最多(空间换时间)
移动对象

分代收集算法(理念)

新生代可以使用复制算法,老年代可以使用标记清除或者标记整理

常见的垃圾收集器

在这里插入图片描述
-XX:+PrintCommandLineFlags,查看使用过的垃圾收集器
-XX:+UseSerialGC,指定使用Serial GC和Serial Old GC
-XX:+UseParNewGC,指定新生代使用ParNew GC
-XX:+UseConMarkSweepGC,指定老年代使用CMS GC
-XX:+UseParallelGC,指定新生代使用ParParallelGC
-XX:+UseParallelSweepGC,指定老年代使用Parallel Old GC

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值