前往小程序,Get更优阅读体验!
立即前往
发布

JVM

作者头像
@派大星
发布2023-06-27 17:12:32
发布2023-06-27 17:12:32
1470
举报
文章被收录于专栏:码上遇见你码上遇见你

JVM(Java Virtual Machine Java虚拟机)的缩写

-它是虚构出来的计算机,是通过实际的计算机仿真模拟各种计算机功能来实现的 JVM包括一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个储存方法域。它屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在各种平台上不加修改的运行。JVM在执行字节码时最终还是把字节码转换成具体平台上的机器指令执行。

JVM被分为三个主要的子系统:

类加载器子系统、运行时数据区、执行引擎

JVM三大核心区域:

JVM三大性能调优参数:-Xms-Xmx-Xss

-Xms-Xmx是对堆的性能调优参数,一般两个设置都是一样的,如果不一样当Heap不够用,会发生内存抖动,一般都调大这两个参数,并且这两个参数一样.

-Xss是对每个线程栈的性能调优参数,影响堆栈条用的深度.

实战演示从OOM推导出JVM GC时候基于的内存结构oung Generation(Eden、From、To)、OldGeneration、Permanent Generation

JVMHeap区域(年轻代、年老代)和方法区(永久代)结构图:

从JavaGC角度解读代码:程序20行代码new 的 person对象首先会进入年轻代的Eden 中(如果对象太大可能直接进入年老代),在GC之前对象是存在Eden和From中,进行GC的时候Eden中的对象被拷贝到To这样一个survive空间(survive (幸存):包括from 和 to,它们的空间大小都是一样的又叫s1 和 s2) 中 (有一个拷贝算法),From中的对象(算法考虑经过GC幸存的次数)到一定次数(阙值(如果说每次GC之后这个对象依旧在Survive中存在,GC一次他的Age就会加1,默认15就会放到OldGeneration.但是实际情况比较复杂,有可能没有到阈值就从Survive区域直接到Old Generation区域.在进行GC的时候会对Survive中的对象进行判断,Survive空间中有一些对象Age是一样的,也就是经过的GC次数一样,年龄相同的这样一批对象的总和大于等于Survive空间一半的话,这组对象就会进入old Generation中,(是一种动态的调整)),会被复制到OldGeneration,如果没到次数From中的对象会被复制到To中,复制完成后To中保存的是有效的对象,Eden和From中剩下的都是无效的对象,这个时候就把Eden和From中所有的对象清空。在复制的时候Eden中的对象进入To中,To可能已经满了,这个时候Eden中的对象就会被直接复制到Old Generation中,From中的对象也会直接进入Old Generation中。就是存在这样一种情况,To比较小,第一次复制的时候空间就满了,直接进入old Generation中。复制完成后,To和From的名字会对调一下,因为Eden和From都是空的,对调后Eden和To都是空的,下次分配就会分配到Eden。一直循环这个流程 好处:使用对象最多和效率最高的就是在Young Generation中,通过From to就避免过于频繁的产生FullGC(Old Generation满了一般都会产生FullGC)

至于持久代中,则主要存储一些常量池、方法区等数据。相关参数如下:

-Xmx:最大堆内存,如:-Xmx512m

-Xms:初始时堆内存,如:-Xms256m

-XX:MaxNewSize:最大年轻区内存

-XX:NewSize:初始时年轻区内存.通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%

-XX:MaxPermSize:最大持久带内存

-XX:PermSize:初始时持久带内存

-XX:+PrintGCDetails。打印 GC 信息

-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3

-XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10

三种基本的GC算法基石:

1.标记/清除算法: 这种方法首先遍历整个区域中的对象,然后标记所有的可达对象,再将所有内存中未被标记的对象全部清除。主要缺点在于会产生大量的碎片内存递归效率低性能低;会停止整个程序运行;

2.复制算法:把内存分成两块区域:空闲区域和活动区域,第一还是标记(标记谁是可达的对象),标记之后把可达的对象复制到空闲区,将空闲区变成活动区,同时把以前活动区对象1,4清除掉,变成空闲区。

优缺点:速度快但耗费空间,假定活动区域全部是活动对象,这个时候进行交换的时候就相当于多占用了一倍空间,但是没啥用。

3.标记/整理算法: 这种方法集上面两种算法的优点于一身,首先遍历整个空间对可达对象进行标记,然后再讲所有可达对象整理到一起去,最后清除掉不可达的对象,达到GC回收清理内存的目的。

Jvm如何检测对象是否有用?

上面一个章节我们简要的叙述了Jvm GC的回收策略,但是大家一定很好奇,Jvm是如何判断一个对象是否已经无人再使用的,这里大致说一下Jvm的策略.

引用计数法
顾名思义,这种方法其实很简单,就是你new出来一个对象之后,之后每次对该对象做了引用,那么就将该对象+1,在GC时,只需要判断该对象对应的count是否为0就可以轻松判断出是否还存在引用关系。

注*:但是这种方法很不严谨,循环引用会使得其产生内存泄漏,永远无法释放这些资源。

根搜索算法

这个算法其实也很简单,如下图所示,Jvm会起一个后台守护进程来维护一个树结构,如果发生引用就在树上维护一条边,那么同样的,如果这个引用被释放了,那么这个类也就和这个树失去了链接,从根节点GC Root对其进行搜索也搜索不到,便可以判断其对象已经无人再引用,可以释放。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上遇见你 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Jvm如何检测对象是否有用?
    • 引用计数法
    • 顾名思义,这种方法其实很简单,就是你new出来一个对象之后,之后每次对该对象做了引用,那么就将该对象+1,在GC时,只需要判断该对象对应的count是否为0就可以轻松判断出是否还存在引用关系。
    • 根搜索算法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档