JVM深入虚拟机系列3-----GC参数,类装载器

JVM深入虚拟机系列2中学习了一些常见的JVM配置参数以及一些GC算法,对于GC可以通过设置不同的参数来选择使用不同的收集器.

一. GC参数

二.类装载器

1.串行收集器

 -XX:+UseSerialGC
 新生代、老年代使用串行回收
 新生代复制算法
 老年代标记-压缩
  • 最古老,最稳定
  • 效率高
  • 可能会产生较长的停顿

在这里插入图片描述

2.并行收集器

  1. ParNew

     -XX:+UseParNewGC
    

    新生代并行
    老年代串行

  • Serial收集器新生代的并行版本
  • 复制算法
  • 多线程,需要多核支持
  • -XX:ParallelGCThreads 限制线程数量

在这里插入图片描述
2. Parallel收集器

  • 类似ParNew

  • 新生代复制算法

  • 老年代 标记-压缩

  • 更加关注吞吐量

      -XX:+UseParallelGC 
      使用Parallel收集器+ 老年代串行
      -XX:+UseParallelOldGC
      使用Parallel收集器+ 并行老年代
    

在这里插入图片描述

  	-XX:MaxGCPauseMills
  • 最大停顿时间,单位毫秒

  • GC尽力保证回收时间不超过设定值

      -XX:GCTimeRatio
    
  • 0-100的取值范围

  • 垃圾收集时间占总时间的比

  • 默认99,即最大允许1%时间做GC

这两个参数是矛盾的。因为停顿时间和吞吐量不可能同时调优

3.CMS收集器

CMS运行过程比较复杂,着重实现了标记的过程,可分为

  • 初始标记
    根可以直接关联到的对象
    速度快
  • 并发标记(和用户线程一起)
    主要标记过程,标记全部对象
  • 重新标记
    由于并发标记时,用户线程依然运行,因此在正式清理前,再做修正
  • 并发清除(和用户线程一起)
    基于标记结果,直接清理对象

在这里插入图片描述

特点

  • 尽可能降低停顿

  • 会影响系统整体吞吐量和性能
    比如,在用户线程运行过程中,分一半CPU去做GC,系统性能在GC阶段,反应速度就下降一半

  • 清理不彻底
    因为在清理阶段,用户线程还在运行,会产生新的垃圾,无法清理

  • 因为和用户线程一起运行,不能在空间快满时再清理
    -XX:CMSInitiatingOccupancyFraction设置触发GC的阈值
    如果不幸内存预留空间不够,就会引起concurrent mode failure

  • 使用串行收集器作为后备
    在这里插入图片描述

  • -XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次整理
    整理过程是独占的,会引起停顿时间变长

  • -XX:+CMSFullGCsBeforeCompaction
    设置进行几次Full GC后,进行一次碎片整理

  • -XX:ParallelCMSThreads
    设定CMS的线程数量

GC参数整理

-XX:+UseSerialGC:在新生代和老年代使用串行收集器
-XX:SurvivorRatio:设置eden区大小和survivior区大小的比例
-XX:NewRatio:新生代和老年代的比
-XX:+UseParNewGC:在新生代使用并行收集器
-XX:+UseParallelGC :新生代使用并行回收收集器
-XX:+UseParallelOldGC:老年代使用并行回收收集器
-XX:ParallelGCThreads:设置用于垃圾回收的线程数
-XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS+串行收集器
-XX:ParallelCMSThreads:设定CMS的线程数量
-XX:CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发
-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的整理
-XX:CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾回收后,进行一次内存压缩
-XX:+CMSClassUnloadingEnabled:允许对类元数据进行回收
-XX:CMSInitiatingPermOccupancyFraction:当永久区占用率达到这一百分比时,启动CMS回收
-XX:UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS回收

4.Tomcat实例演示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

1.class装载验证流程

- 加载
- 链接
	1. 验证
	2. 准备
	3. 解析
- 初始化

加载
装载类的第一个阶段
取得类的二进制流
转为方法区数据结构
在Java堆中生成对应的java.lang.Class对象

链接 -> 验证

  • 目的:保证Class流的格式是正确的
    • 文件格式的验证
      • 是否以0xCAFEBABE开头
      • 版本号是否合理
    • 元数据验证
      • 是否有父类
      • 继承了final类?
      • 非抽象类实现了所有的抽象方法
    • 字节码验证 (很复杂,通过字节码检查不一定没有问题,没有通过字节码检查一定有问题)
      • 运行检查
      • 栈数据类型和操作码数据参数吻合
      • 跳转指令指定到合理的位置
    • 符号引用验证
      • 常量池中描述类是否存在
      • 访问的方法或字段是否存在且有足够的权限

链接 -> 准备

  • 分配内存,并为类设置初始值 (方法区中)
    - public static int v=1;
    - 在准备阶段中,v会被设置为0
    - 在初始化的中才会被设置为1
    - 对于static final类型,在准备阶段就会被赋上正确的值
    - public static final int v=1;

链接 -> 解析

  • 符号引用(字符串引用对象不一定被加载)替换为直接引用(指针或者地址偏移量引用对象一定在内存)

初始化

  • 执行类构造器
    static变量 赋值语句
    static{}语句
  • 子类的调用前保证父类的被调用
  • 是线程安全的

2.什么是类装载器ClassLoader

  • ClassLoader是一个抽象类
  • ClassLoader的实例将读入Java字节码将类装载到JVM中
  • ClassLoader可以定制,满足不同的字节码流获取方式
  • ClassLoader负责类装载过程中的加载阶段

3.JDK中ClassLoader默认设计模式ClassLoader

ClassLoader的重要方法

  • public Class<?> loadClass(String name) throws ClassNotFoundException
    载入并返回一个Class
  • protected final Class<?> defineClass(byte[] b, int off, int len)
    定义一个类,不公开调用
  • protected Class<?> findClass(String name) throws ClassNotFoundException
    loadClass回调该方法,自定义ClassLoader的推荐做法
  • protected final Class<?> findLoadedClass(String name)
    寻找已经加载的类

分类

  • BootStrap ClassLoader (启动ClassLoader)

  • Extension ClassLoader (扩展ClassLoader)

  • App ClassLoader (应用ClassLoader/系统ClassLoader)

  • Custom ClassLoader(自定义ClassLoader)

  • 每个ClassLoader都有一个Parent作为父亲

协同工作

在这里插入图片描述
loadClass方法的实现

在尝试加载一个类的时候,先去找这个类是否已经被加载,如果被加载了就返回这个类,如果找不到 ,就去请求父类去加载.
在尝试加载一个类的时候,先去找这个类是否已经被加载,如果被加载了就返回这个类,如果找不到 ,就去请求父类去加载.
在这里插入图片描述

  • 直接运行以上代码:
    • I am in apploader
  • 加上参数 -Xbootclasspath/a:D:/tmp/clz
    • I am in bootloader
    • 此时AppLoader中不会加载HelloLoader
      • I am in apploader 在classpath中却没有加载
      • 说明类加载是从上往下的

在这里插入图片描述

4.打破常规模式

问题:
在这里插入图片描述
解决:

Thread. setContextClassLoader()

  • 上下文加载器
  • 是一个角色
  • 用以解决顶层ClassLoader无法访问底层ClassLoader的类的问题
  • 基本思想是,在顶层ClassLoader中,传入底层ClassLoader的实例
    在这里插入图片描述

双亲模式的破坏

  • 双亲模式是默认的模式,但不是必须这么做
  • Tomcat的WebappClassLoader 就会先加载自己的Class,找不到再委托parent
  • OSGi的ClassLoader形成网状结构,根据需要自由加载Class
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

5.热替换ClassLoader

含义:

  • 当一个class被替换后,系统无需重启,替换的类立即生效
    例子:
    geym.jvm.ch6.hot.CVersionA
public class CVersionA {
	public void sayHello() {
		System.out.println("hello world! (version A)");
	}
}

  • DoopRun 不停调用CVersionA . sayHello()方法,因此有输出:
    • hello world! (version A)
  • 在DoopRun 的运行过程中,替换CVersionA 为:
public class CVersionA {
	public void sayHello() {
		System.out.println("hello world! (version B)");
	}
}
  • 替换后, DoopRun 的输出变为
    • hello world! (version B)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值