JVM

一、JVM内存模型

在这里插入图片描述

堆内存
	1、JVM实质上分为三大块:
		年轻代(YoungGen),年老代(Old Memory),及持久代(Perm,在Java8中被取消)
	2、垃圾回收GC,分2种:
			Minor GC,可以可以称为YGC(年轻代);
			Major GC,又称为FullGC(老年代);

	3、对象存储过程:
		刚被new出来的时候,放到Eden区。
		Eden区空间不足,发生YGC,没有被任何其他对象所引用的对象将会从内存中被清除,
			还被其他对象引用的则放到幸存者区(幸存者1区和幸存者2区其中一个)。
		幸存者区多次没有被清除的对象,则会被移到老年代区。
		当老年代区域被占满的时候,则会发送FullGC。这时只允许GC进程进行垃圾回收。
	
	4、无论是YGC或是FullGC,都会导致程序会停止运行stop-the-world,执行一次时间
		在40秒至3分钟的fullgc,部分web或socket程序,当终端连接的时候会
		报connetTimeOut或readTimeOut异常,
	
	5、从JVM调优的角度来看,我们该尽量避免发生YGC或FullGC,或者使得YGC和FullGC的时间
		足够的短。
		
	JDK1.8之后,之前的永久代区被元空间区取代,元空间区不在JVM内存中,在操作系统内存中
	内存溢出:旧对象仍然保持引用时不断创建新对象,使得堆内存空间满至溢出的现象
	内存泄漏:旧对象已经无实际职责,但是没有将其引用设置为null,导致其无法被回收,
	         一直占据内存空间的现象
	内存泄漏会导致内存的实际可用空间不断变小,最终引发内存溢出。
1. JVM Java进程 
2. JVM (堆空间) HBase
   新生代 1/3                             老年代 2/3  永久代(静态,常量)
   eden survivor(from)  survivor(to)
    8      1                1
   ParNewGC                              ConcMarkSweepGC
   ”-Xmx8g -Xms8G -Xmn128m -XX:UseParNewGC  -XX:UseConcMarkSweepGC -   XX:CMSInitiatingOccupancyFraction=70  -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:$HBASE_HOME/logs/gc-${hostname}-hbase.log”
 
   hbase-env.sh
   export HBASE_REGIONSERVER_OPTS=-Xmx8g -Xms8G  -Xmn128m -XX:UseParNewGC     -XX:UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70  -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps    -Xloggc:$HBASE_HOME/logs/gc-${hostname}-hbase.log”

二、 运行时数据区

在这里插入图片描述

三、JVM类加载

2.1 类加载过程

在这里插入图片描述

验证:
	 文件格式,符号引用,字节码,元数据
准备:
 	 对静态变量分配内存,使用默认值(特殊:被final修饰的static变量在编
 	 译期进入常量池)
解析:
 	将符号引用(用符号指向目标的指针)转化为直接引用(指针,相对偏移量,
 	间接指向目标的句柄)

初始化:
	对当前类父类或者超类对其实例化(不完全加载),对静态变量进行赋
	值,对成员变量赋予默认值

2.2、类加载器

  • 加载过程----通过类加载器将格式为.class的文件加载入JVM。

2.2.1 启动类加载器(Bootstrap)

  C++编写 加载的时候,根据类的权限定名读取核心类库(以java、javax、sun,
  	 特殊的(rt.jar))
  ---将核心类库JDK加载到 虚拟机内存中,
     为保证虚拟机安全(),没有父类。

2.2.2 拓展类加载器(Extension)

java编写  父类 null
	读取外部引入类库(通常为项目中引入的第三方jar包)

2.2.3 系统类加载器(System)

(application)java编写 
	父类 拓展类加载器
	读取classpath下的类	

2.2.4 自定义类加载器

  父类  系统类加载器

2.3、双亲委派机制

	当JVM需要一个类的类信息时,首先从调用loadclass方法从内存中尝试读取该类信息,
读取时从自定义类加载器逐级向上,直至读取到为止。如果未能读取,则从bootstrap类加
载器开始调用findclass方法尝试进行加载,如果不能读取则逐级向下委派,如果都不能读
取,则抛出ClassNotFoundException。

类加载的两种方式:
显式:一般的类的加载。
隐式
	Class.forName  this.getClass().getClassLoader().loadclass()

双亲委派机制的破坏者:
	线程上下文类加载器---读取rt.jar中的接口实现方法
举例:JDBC中对驱动的加载,使用的显示加载,因为该类无法被双亲委派隐式加载

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

  • 反编译
    在这里插入图片描述

四、虚拟机配置

4.1 IDEA虚拟机配置

-Xms128m  
	  Java Heap初始值,Server端JVM最好将-Xms和-Xmx设为相同值,
	  开发测试机JVM可以保留默认值

-Xmx750m
	java Heap最大值,默认值为物理内存的1/4,最佳设值应该视物理
	内存大小及计算机内其他内存开销而定
	
-XX:ReservedCodeCacheSize=240m 
		预留保存代码的内存空间大小。
		
-XX:+UseConcMarkSweepGC 
		老年代使用 CMS 垃圾回收策略(并发标记清除)
		
-XX:SoftRefLRUPolicyMSPerMB=50
	意思是最近最少被引用的软引用 将在50秒后被JVM清除。单位为秒。
	
-ea  
	ea 开启断言 -da 禁止断言
	
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
	如果在使用ipv4的机器上运行启用了ipv6的系统,那么此参数设为true才
	能获取机器的完整机器名

-Djdk.http.auth.tunneling.disabledSchemes=""
	根据域名自动下载https服务端发送过来的证书并保存成文件

-XX:+HeapDumpOnOutOfMemoryError
		当堆内存空间溢出时输出堆的内存快照

-XX:-OmitStackTraceInFastThrow
	省略异常栈信息从而快速抛出,JVM对一些特定的异常类型做了Fast Throw优化,
	如果检测到在代码里某个位置连续多次抛出同一类型异常的话,C2会决定用Fast Throw方
	式来抛出异常,而异常Trace即详细的异常栈信息会被清空。这种异常抛出速度非常快,
	因为不需要在堆里分配内存,也不需要构造完整的异常栈信息

4.3 虚拟机配置分析

java 
-server 
-Xms4G -Xmx4G -Xmn2G 
-XX:SurvivorRatio=1 
-XX:+UseConcMarkSweepGC 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=1100 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false 
-jar c1000k.jar&

-Xms4G 是指: JVM启动时整个堆(包括年轻代,年老代)的初始化大小。
-Xmx4G 是指: JVM启动时整个堆的最大值。
-Xmn2G是指:年轻代的空间大小,剩下的是年老代的空间。

-XX:SurvivorRatio=1是指:年轻代空间中2个Survivor空间与Eden空间的大小比例。
	此处为1:1:1,算法如下:比如整个年轻代空间为2G,如果比例为1,那么2/3,
	则S0/S1/Eden的空间大小是同样的,为666M。
	该值不设置,则JDK默认为比例为8,那么是1:1:8,通过上面的算法可以得出S0/S1的大小。
	我们可以看到官方通过增大Eden区的大小,来减少YGC发生的次数,但有时我们发现,
	虽然次数减少了,但Eden区满的时候,由于占用的空间较大,导致释放缓慢,
	此时stop-the-world的时间较长,因此需要按照程序情况去调优。
	
-XX:+UseConcMarkSweepGC是指:使用GC的回收类型。这里是CMS类型,JDK1.7以后推荐
	使用+UseG1GC,被称为G1类型(或Garbage First)的回收器
再服务器上执行:jstat -gc 15016 1000,看到每1秒钟java进程号为15016的GC回收情况

root@sxxd ]# jstat -gc 1500 1000
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
699008.0 699008.0 29980.4 0.0 699136.0 116881.6 2097152.0 660769.4 21248.0 20071.0 354 54.272 0 0.000 54.272

699008.0 699008.0 29980.4 0.0 699136.0 118344.8 2097152.0 660769.4 21248.0 20071.0 354 54.272 0 0.000 54.272

699008.0 699008.0 29980.4 0.0 699136.0 119895.5 2097152.0 660769.4 21248.0 20071.0 354 54.272 0 0.000 54.272

699008.0 699008.0 29980.4 0.0 699136.0 121383.1 2097152.0 660769.4 21248.0 20071.0 354 54.272 0 0.000 54.272

  • 解释
S0C 是指:Survivor0区的分配空间
S0U 是指:Survivor1区的已经使用的空间

EC是指: Eden区所使用的空间
EU是指:Eden区当前使用的空间

OC是指:老年代分配的空间
OU是指:老年代当前使用的空间

PC是指:持久待分配的空间
PU是指:持久待当前使用的空间

YGC是指:年轻代发生的次数,这里是354次
YGCT是指:年轻代发送的总时长,这里是54.272秒,因此每次年轻代发生GC,
			即平均每次stop-the-world的时长为54.272/354=0.153秒。

FGC是指:年老代回收的次数,或者成为FullGC的次数。
FGCT是指:年老代发生回收的总时长。

GCT是指:包括年轻代YGC及年老代FGC的总时间长。
  • 通常
  • 当EU即将等于EC的时候,此时发生YGC,因此YGC次数+1,YGCT时间增加。
  • 发生YGC的时候,如果S0U或S1U区如果有任意一个区域为0的时候,此时YGC的速度很快,相反如果S0U或者S1U中都有数据,或相对满的时候,此时YGC的时间边长,这就是因为S0/S1及Eden区的比例问题导致的
  • 经过调优,使得YGC的次数非常少,时间非常快,很长时间,数天都不会发生FGC,此时JVM的调优算是一个好的结果。

4.3 GC日志分析

在这里插入图片描述

	Full GC:对整个堆内存空间的一次垃圾回收
	GC:对年轻代空间的一次垃圾回收
	Allocation Failure:“分配失败”,即为新对象分派内存不够
	System.gc():执行该方法触发的GC
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值