JVM知识点

JVM 分为三个模块:

 1、类加载子系统

 2、运行时数据区

 3、执行引擎

类加载过程:

1 、加载(将磁盘class文件加载到内存)

2、连接

     2.1、验证

     验证字节码的正确性

     2.2、准备

      给类的静态变量分配内存 并赋值默认值

     2.3、解析

       类装载器装载类所引用的其他类  

3、初始化

       为类的静态变量赋予正确的初始值,上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值,执行静态代码块

4、使用

5、卸载

类加载器种类:

启动类加载器(Bootstrap ClassLoader)

负责加载JRE的核心类库,如JRE目标下的rt.jar,charsets.jar等

扩展类加载器(Extension ClassLoader)

负责加载JRE扩展目录ext中jar类包

系统类加载器(Application ClassLoader)

负责加载ClassPath路径下的类包

用户自定义加载器(User ClassLoader)

负责加载用户自定义路径下的类包

如何打破双亲委派?

我们需要继承ClassLoader类,然后重写loadClass和findClass就可以了。

运行时数据区

1、方法区(以前叫永久代,后来为了融合JRockit和HotSpot改为方法区,1.8之后用元空间来实现了方法区)

2、堆(新生代、老年代)

3、虚拟机栈

4、本地方法栈

5、程序计数器

如何判断对象是否可以被回收

1、引用计数法

给对象添加一个引用计数器,每当有一个地方引用,计数器就加1。当引用失效,计数器就减1。任何时候计数器为0的对象就是不可能再被使用的。

2、可达性分析算法(安全点的概念,可以不停机的再安全点挂起可以被挂起的线程)

这个算法的基本思想就是通过一系列的称为”GC Roots“的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连的话,则证明此对象时不可用的。

GC Roots根节点:类加载器、Thread、虚拟机栈的局部变量表、static成员、常量引用、本地方法栈的变量等等

垃圾回收算法:

1、标记-清除

即把死亡对象所占据的内存标记为空闲内存,并记录在一个空闲列表(free list)之中。当需要新建对象时,内存管理模块便会从该空闲列表中寻找空闲内存,并划分给新建的对象。

缺点:

有空间碎片,由于 Java 虚拟机的堆中对象必须是连续分布的,因此可能出现总空闲内存足够,但是无法分配的极端情况。另一个则是分配效率较低。如果是一块连续的内存空,那么我们可以通过指针加法(pointer bumping)来做分配。而对于空闲列表,Java 虚拟机则需要逐个访问列表中的项,来查找能够放入新建对象的空闲内存。

2、标记-压缩

即把存活的对象聚集到内存区域的起始位置,从而留下一段连续的内存空间。这种做法能够解决内存碎片化的问题,但代价是压缩算法的性能开销。

缺点:压缩算法有性能开销

3、复制算法

即把内存区域分为两等分,分别用两个指针 from 和 to 来维护,并且只是用 from 指针指向的内存区域来分配内存。当发生垃圾回收时,便把存活的对象复制到 to 指针指向的内存区域中,并且交换 from 指针和 to 指针的内容。复制这种回收方式同样能够解决内存碎片化的问题,但是它的缺点也极其明显,即堆空间的使用效率极其低下。

垃圾回收器:

新生代:Serial  、Parallel Scavenge、   Parallel New(三个都是标记 - 复制算法)

老年代:

Serial Old (标记-压缩)、 Parallel Old(标记-压缩)、

CMS(标记-清除算法,可以在不用stop-the-world进行并行垃圾回收 但java9中被废弃因为G1横空出世)

G1(标记 - 压缩算法):是一个横跨新生代和老年代的垃圾回收器。它已经打乱了前面所说的堆结构,直接将堆分成极其多个区域。每个区域都可以充当 Eden 区、Survivor 区或者老年代中的一个。可以在不用stop-the-world进行并行垃圾回收

cms垃圾回收器和g1有什么区别?

区别一: 使用范围不一样

    CMS收集器是老年代的收集器,可以配合新生代的Serial和ParNew收集器一起使用

    G1收集器收集范围是老年代和新生代。不需要结合其他收集器使用

区别二: STW的时间

CMS收集器以最小的停顿时间为目标的收集器。

G1收集器可预测垃圾回收的停顿时间(建立可预测的停顿时间模型)

区别三: 垃圾碎片

CMS收集器是使用“标记-清除”算法进行的垃圾回收,容易产生内存碎片

G1收集器使用的是“标记-整理”算法,进行了空间整合,降低了内存空间碎片。

区别四: 垃圾回收的过程不一样

CMS收集器                      G1收集器

1. 初始标记                   1.初始标记

2. 并发标记                   2. 并发标记

3. 重新标记                   3. 最终标记

4. 并发清楚                   4. 筛选回收

参考链接文章:

https://www.cnblogs.com/chenpt/p/9803298.html

你们线上应用的 JVM 参数有哪些?

-server -Xmx2g -Xms2g -Xmn256m -XX:PermSize=128m -Xss256k -XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -XX
:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSI
nitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70

-Xms2g JVM初始分配的内存由-Xms指定,默认是物理内存的1/64但小于1G。
-Xmx2g JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4但小于1G。
-XX:PermSize=128m  装载Class信息等基础数据,默认64M
-Xss256k  设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K
-XX:DisableExplicitGC禁止调用代码System.gc()
-XX:+UseConcMarkSweepGC  指定在 Old Generation 使用 concurrent cmark sweep gc,gc thread 和 app thread 并行 ( 在 init-mark 和 remark 时 pause app thread). app pause 时间较短 , 适合交互性强的系统 , 如 web server
-XX:+CMSParallelRemarkEnabled 在使用 UseParNewGC 的情况下 , 尽量减少 mark 的时间
XX:+UseCMSCompactAtFullCollection 在使用 concurrent gc 的情况下 , 防止 memory fragmention, 对 live object 进行整理 , 使 memory 碎片减少
-XX:LargePageSizeInBytes=128m  指定 Java heap 的分页页面大小 , 如 :-XX:LargePageSizeInBytes=128m
-XX:+UseFastAccessorMethods get,set 方法转成本地代码
-XX:+UseCMSInitiatingOccupancyOnly  指示只有在 old generation 在使用了初始化的比例后 concurrent collector 启动收集
XX:CMSInitiatingOccupancyFraction=70 指示在 old generation 在使用了 n% 的比例后 , 启动 concurrent collector, 默认值是 68, 如 :-XX:CMSInitiatingOccupancyFraction=70

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值