初识JVM虚拟机

初识JVM虚拟机

 

面试经常会问到,对JVM的了解

其实无非问的最多的是:

1.jvm的内存区域分配

2.jvm的GC

3.jvm的调优

 

JVM的内存区域分配

先放一张偷来的图,哈哈~

先了解什么是jvm?

JRE有java API和JVM组成,JVM通过类加载器(Class Loader)加载类Java应用,并通过Java API进行执行。

JVM本身就是一个用于执行java字节码的执行器。

由上图可以看出:

JVM的内部体系结构分为三部分,分别是:类装载器子系统、运行时数据区和执行引擎。

类装载器子系统:每一个java虚拟机都由一个类加载子系统,负责加载程序中的类型(类和接口),并赋予唯一的名字。JVM的两种类装载器包括:启动类装载器和用户自定义类装载器,启动类装载器是JVM实现的一部分,用户自定义类装载器则是Java程序的一部分,必须是ClassLoader类的子类。

执行引擎:负责执行被加载类中包含的指令。

运行时数据区:堆、方法区、本地方法栈、虚拟机栈、程序计数器。

 

其实我们的重点是运行时数据区!!!

再偷一张图,哈哈~

现在说JVM的运行内存区域分配?

堆:线程共享,存放所有程序运行时创建的对象以及数组值的区域,堆中的对象内存需要等待GC进行回收。

方法区:线程共享,又称持久态,当JVM的类装载器加载class文件并进行解析,把解析的类信息、静态变量、常量等等存入方法区,在一定条件下也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OOM的错误信息。

程序计数器:线程私有,又叫PC寄存器,每个线程都有自己的PC寄存器,也是该线程启动时创建的,寄存器的内容总是指向下一条将执行指令的地址,若线程执行java方法,则PC保存下一条执行指令的地址,若执行native方法,则PC的值为undefined

虚拟机栈:线程私有,存放的为当前线程中方法局部基本类型的变量、部分返回的结果

本地方法栈:线程私有,存储本地方法调用的状态

 

JVM的GC

GC的问题比较多,我们一个一个来

1.什么是GC?

垃圾回收机制

将垃圾对象进行回收,释放内存,防止内存泄漏,有效的使用可以使用的内存,对内存中已死亡的或者长时间没有使用的对象进行清除和回收。

2.关于GC判断垃圾的算法

引用计算法:

通过在对象中分配一个空间来保存该对象被引用的次数,如果该对象被其他对象引用,引用计数+1,如果删除对该对象的引用,引用计数-1,当该引用计算为0时,那么该对象就会被回收(缺陷:相互引用的情况下,引用计数永不为0)。

可达性分析算法:

可达性分析算法的基本思路是,通过一些被称为引用链的对象作为起点,从这些起点开始向下搜索,搜索走过的路径被称为Reference Chain,当一个对象到GC Roots没有任何引用链相连时,(即从GC Roots节点代该节点不可达)则证明该对象不可用

在Java中,可作为GC Roots的对象包括以下几种:

  1. 虚拟机栈中引用的对象
  2. 方法区中类静态属性引用的对象
  3. 方法区中常量引用的对象
  4. 本地方法栈中JNI引用的对象

3.关于GC回收的算法

标记-清除法:

是最基础的一种垃圾回收算法,分为两部分,先把内存区域中的这些对象进行标记,那些属于可回收的

标记出来,然后把标记出来的垃圾进行清理掉(缺陷:产生内存碎片,内存需要连续的)。

复制算法:

将内存按容量分为大小相等的两块,每次只使用其中的一块,当这块的内存用完了,就将还存活的对象复制到另一块上面,然后将已使用的内存空间一次清理掉,保证了内存的连续性(缺陷:只使用一般,代价太高)。

标记-整理法:

标记过程仍然和标记清除算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都想一端移动,在清理端边界以外的内存区域(缺陷:内存变动频繁,需要整理所有存活对象的引用,效率低)。

分代收集算法:

简单来说,这不算是一种算法,而是一种根据各个算法的优点总结出来的方案。

将对象存活周期的不同将内存划分为N块,一般是将对分为新生代和老年代,这样就可以就可以根据各个年代的特点采用最适当的收集算法,在新生代中,每次垃圾收集时,都有大批对象死去,只用少量存活,那就选择复制算法,只需要付出少量的存活对象的复制成本,而老年代中因为存活效率高,没有额外的空间对它进行分配担保,就必须使用标记-清除法或者标记-整理法来进行回收。

4.新生代、老年代和持久代?

年轻代:年轻代分为三个区,一个Eden区,两个Survivor区。大部分对象在Eden区生成。当Eden区满时,还存活的对象将被复制到Survivor区,当这个Survivor区也满的时候,从第一个Survivor区复制过来的并且还存活的对象,将被复制到年老区。(两个Survivor分别是From区和To区)。

年老代:年老代存放从年轻代存活的对象,一般来说年老代存放的都是生命周期较长的对象。

持久代:用于存放静态文件,如java类、方法等。持久代对垃圾回收没有显著影响。

将内存中不再被使用的对象进行回收,GC用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对象的生命周期特征进行分析后,按照新生代、旧生代的方式进行对对象的收集,以尽可能的缩短GC对应用造成的暂停

  1. 对新生代的对象的收集称为minor GC
  2. 对旧生代的对象的收集称为Full GC
  3. 程序中主动调用System.gc()强制执行的GC为Full GC

不同的对象引用类型,GC会采用不同的方法进行回收,JVM对象的引用类型分为四种:

  • 强引用:默认情况下,对象采用的均为强引用(这个对象的实力没有其他对象引用,GC时才会被回收)
  • 软引用:软引用是Java中提供的一种比较适合于缓存场景的引用(只用在内存不够用的情况下才会被GC)
  • 弱引用:在GC时一定会被GC回收
  • 虚引用:由于虚引用只是用来得知对象是否被GC

未完待续。。。

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值