JVM简单介绍

JVM简单介绍(持续更新)

JVM的组成部分

JVM主要由类加载器运行时数据区执行引擎本地方法接口组成。
运行时数据区:

  • :用于存放创建出的对象,程序中创建的所有对象都放在堆中,堆内存的生命周期由垃圾回收器进行管理,堆中主要分为三个部分
    • 新生代:存放新建的对象
    • 老年代:当经历过一定次数的GC(垃圾回收)还存活的对象会放入老年代
    • 持久代:存储运行时必须的类信息,此区域的数据不会进行GC,直到进程关闭才会释放这块内存(ps:jdk1.8之后这块区域存放的数据修改为存放至元空间)。
  • :维护方法之间的调用关系(栈可以有多个,每个线程都能有一个)
    • java虚拟机栈:用于存放线程执行方法过程中的局部变量、方法返回结果(ps:包括方法的正常返回或者异常信息)、操作数栈等。java虚拟机栈的生命周期与线程相同,每一个方法执行时都会在虚拟机栈创建一个栈帧,栈帧包含方法的参数、局部变量以及方法执行过程中的中间结果和最终结果,当方法执行完成后弹出。
    • 本地方法栈:本地方法栈与虚拟机栈类似,不过本地方法栈是给本地方法(Native修饰的方法)用的。
  • 方法区(旧)/元数据区(新):放的是类加载(加载类的信息、常量(ps:非编译时常量)、静态变量、即时编译器编译后的代码等数据)
  • 程序计数器:记录当前程序执行到了哪个指令(可有多个,每个线程都能有一个),本质是一个指针,用来指向方法区中的方法(用来存储指向下一条指令的地址)。

JVM的参数信息(可能常用参数)

  • Xms:为JVM启动时申请的最小内存,默认为操作系统物理内存的1/64但小于1g
  • Xmx:为JVM可申请的最大内存,默认为操作系统物理内存的1/4但小于1g
  • XX:MinHeapFreeRation:默认当空余堆内存小于40%时,JVM会增大Heap到-Xmx指定的大小,可通过该参数指定这个比列。
  • XX:MaxHeapFreeRation:默认当空余堆内存大于70%时,JVM会减小heap的大小到-Xms指定的大小,可通过该参数指定这个比列。
  • Xmn:设定年轻代的大小,整个堆大小=年轻代大小+年老代大小+持久代大小,持久代大小一般默认为64m,所以增大年轻代大小,将会减少年老代的大小,此值对系统性能影响较大,sun官方推荐年轻代大小为整个堆大小的3/8。
  • Xss:设置每个线程的最大栈空间

垃圾回收机制

垃圾回收机制(Gabage Collection,简称GC)是内存管理的核心组成部分,它负责回收不再使用的内存空间,一旦对象不再被引用,垃圾回收器就会在适当的时机回收它们所占用的内存
垃圾收回主要分为两个步骤:
 - 查询内存中不再使用的对象(GC判断策略):
       - 引用计数算法:给对象添加一个引用计数器,当对象增加一个引用的时候计数器+1,引用失效时计数器-1。引用计数为0的对象可被回收。但当两个对象循环依赖的时候计数器永远不会为0,导致它们无法被回收。正因为此情况,java虚拟机不使用引用计数算法。
       - 可达性分析算法:把对象之间的引用关系理解成一个树形结构,从一些特殊的起点(栈上的局部变量、常量池中的引用对象、方法区中静态成员引用的对象)出发,进行遍历,将不能访问到的对象进行回收。但在遍历过程中,对象之间的引用关系产生了变化就会对分析产生影响,所以在遍历过程中需要将其他的业务线程暂停工作,这个问题成为STW问题。目前这个问题也没有得到解决,只是将业务线程暂停的时间大大减少了。  
 - 释放这些对象占用的内存(GC回收算法):
       - 标记清除算法:算法分为标记和清除两个阶段,首先标记出所有需要进行回收的对象,在标记完成后统一进行清除操作。标记和清除的过程效率并不高,并且在清除对象后可能会造成大量的空间碎片,导致内存利用率较低,当需要给大对象分配内存时可能无法找到足够的连续内存空间供其使用,进而提前触发下一次GC。
       - 复制算法:算法将可用内存按照容量分为大小相等的两块内存空间,每次只使用其中一块,当此块内存空间需要进行GC时,会将此内存空间内不需要进行GC的对象复制到另一块未使用的内存空间上,然后将之前使用的内存空间全部清理掉,这样大大增加了清理的效率,并且不会产生较多空间碎片。但由于每次只使用一般的内存空间,导致内存利用率较低,并且当大部分对象都不进行GC时,此时的复制成本较高(在老年代中一般不使用复制算法)。
       - 标记整理算法:标记过程与标记清除算法一致,在标记完成后将所有的存活对象都向内存空间的一端移动,然后直接清理端边界以外的内存。
       - 分代回收算法:当前JVM垃圾回收采用的是分代回收算法,算法根据对象的存活周期将不同的内存划为几块,一般是把堆分为新生代和老年代。在新生代中,每次GC都会有大量的对象被回收,所以使用复制算法,而老年代中对象存活率比较高,所以使用标记清除算法或者标记整理算法。

类的加载

类的加载主要分为三个过程:加载、连接和初始化,其中连接还分为验证、准备和解析三个过程。
  • 加载:类的加载主要是将类的.class文件的二进制数据加载进运行时数据库的方法区当中,并且会在堆区创建一个.class文件对应的对象,用来封装方法区中的类的数据结构。
  • 连接:连接就是把已经读入到内存当中的类的二进制数据合并到虚拟机的运行时环境中去。
    • 验证:主要验证类文件的结构、语义、字节码、二进制兼容等。
    • 准备:准备阶段会为类的静态变量分配内容,并设置默认初始值。
    • 解析:解析阶段主要将类当中的符号引用(完全限定名+方法名)替换成直接引用(引用类中的方法在方法区中的地址)。
  • 初始化:初始化阶段java虚拟机会执行类的初始化语句并且为类的静态变化赋予初始值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值