java虚拟机简单介绍

jvm

使用软件模拟java字节码的指令集

jvm的发展历史
  1. 1996年jdk1.0(sun)发布 :纯解释运行
  2. 1997年jdk1.1发布,AWT、内部类、jdbc、rmi、反射
  3. 1998年jdk1.2发布,java分se、me、ee,加入swing
  4. 2000年jdk1.3发布,Hotspot作为默认虚拟机
  5. 2002年jdk1.4发布,classic vm退出历史,加入assert、nio、ipv6、日志
  6. 2004年jdk1.5发布,加入泛型、注解、枚举、装箱、变长参数、foreach
  7. 2006年jdk1.6发布,加入脚本语言支持、jdbc4.0
  8. 2011年jdk1.7发布,加入动态语言增强、nio2.0、加入G1
  9. 2014年jdk1.8发布,lambda表达式,函数式编程

jvm运行机制

1. java xxx 执行运行命令
2. 装载配置(jvm.cnf)
3. 寻找dll(jvm.dll为java虚拟机的主要实现)
4. 初始化jvm(JNIEnv为jvm接口,findClass通过它实现)
5. 找到mian方法并运行
jvm的内部结构

jvm的内部结构

pc寄存器
每个线程都有一个独立的pc寄存器
方法区
保存装载的类信息
java堆
应用系统对象保存、所有线程共享堆、gc的主要工作空间、堆也是分代的(分代gc)
java栈
线程私有,栈由一些列帧组成、帧保存一个方法的局部变量、操作数栈、常量池指针,每一个方法调用创建一个帧、并压栈
可见性

一个线程修改了变量,其他线程可以立即知道

保证可见性方式
volatile
synchronized unlock之前,将变量值写会主存
final 一旦初始化完成,其他线程可见
有序性

本线程内,操作都是有序的

在线程外观察,操作都是无序的(指令重排或者主存延时)

指令重排

保证线程内按顺序执行的结果完全相同

指令重排原则:
顺序原则:一个线程内保证语义的串行性
volatile规则:volatile变量的写,先发生于读
锁规则:解锁必然发生于随后的加锁前
传递性:a先于b,b先于c,则a必然先于c
线程的start先于他的每一个动作
线程的所有操作先于线程的终结
线程的中断先于被中断的线程的代码
对象的构造函数的执行结束先于finalize()方法

jvm的配置参数

trace跟踪参数
-verbose:gc   (打开gc跟踪日志)
-XX:+PrintGC  打印gc简要信息
-XX:+PrintGCDetails 打印gc详细信息
-XX:+PrintGCTimeStamps 打印gc发生的时间戳
-Xloggc:log/gc.log  指定gc的log文件的位置
-XX:+PrintHeapAtGC  每一个gc后,打印堆信息
-XX:+TraceClassLoading  监控类的加载
-XX:+PrintClassHistogram  按下ctrl+break后,打印类的信息(分别显示:序号、实例数量、总大小、类型)
堆的分配参数
-Xmx -Xms  指定最大堆和最小堆空间
-Xmx20m    最大可用20m
-Xms5m     初始化占用5m
-Xmn       设置新生代的大小的绝对值
-XX:NewRatio 设置新生代的大小比例(设置4 表示 新生代:老年代=14,即年轻代占堆的1/5) 官方推荐占3/8
-XX:SurvivorRatio 设置两个survivor和Eden的比(设置8 表示s:e=2:8,即一个survivor占年轻代的1/10) 官方推荐占1/10
-XX:HeapDumpOnOutOfMenoryError 发生内存溢出时导出堆到文件
-XX:+HeapDumpPath 设置发生内存溢出导出文件的路径
-XX:OnOutOfMenoryError  在发生内存溢出时执行一个脚本
永久区分配参数
-XX:PermSize    设置永久区的大小
-XX:MaxPermSize 设置永久区的最大空间大小
如果堆空间未使用完,发生了内存溢出,则有可能是永久代内存溢出
栈大小的分配

通常只有几百k决定了函数调用的深度每个线程都有独立的栈空间局部变量、参数分配在栈上

-Xss 分配栈空间的大小(e:-Xss128k)
GC算法和种类

GC:垃圾回收,GC的回收目标是堆空间和永久区

引用计数法

通过引用计算来回收垃圾 为每个对象设计一个引用计数器,如果有对象引用该对象,则计数加1,引用释放,则计数减1 比较影响性能,始终都伴随着应用加和减 很难处理循环引用 java中没有被使用

标记-清除算法

现代垃圾回收算法的思想基础 分为标记阶段(通过根节点,标记所有从根节点开始的可达对象,未被标记的对象即是垃圾对象)和清除阶段(清除所有未被标记的对象)

标记-整理算法

适用于存活对象较多的场合,如老年代 从根节点开始,对所有可达对象做一次标记,之后将所有存活对象整理到内存的一端,然后清理边界外的所有空间

复制算法

是一种相对高效的算法 不适用于存活对象较多的场合 将原有空间分为两块,每次只使用其中一块,垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存中,之后清除正在使用块的所有对象,然后交换两个内存角色 比较浪费空间

分代思想

依据对象的存活周期,存活时间短的归为新生代,存活时间长的对象为老年代 根据不同代的特点,选取合适的收集算法(少量对象存活,适合复制算法)(大量对象存活,适合标记清除和标记整理)

可触及性

可触及的从根节点可以触及到这个对象

可复活的一旦所有引用被释放,就是可复活状态 在调用finalize()中可能复活的对象

不可触及的执行finalize()之后会进入不可触及状态 不可触及的对象不可能复活 可以被垃圾回收器回收

finalize()方法只会被调用一次,在第一次执行gc调用,之后的gc操作不会调用finalize()

注意事项

避免使用finalize(),操作不慎可能导致错误 gc的调用不确定 可以使用try-catch-finally处理资源的释放

根节点

栈中引用的对象 方法区中静态成员或者常量引用的对象 JNI(java native 方法)方法栈中引用的对象

Stop-The-World

java中一种全局暂停的现象 全局停顿,所有java代码停止,native代码可执行,但不能和jvm交互 多半由于gc引起(dump线程,死锁检查,堆dump也可能引起) 可能会导致(长时间停止服务,没有响应 高可用系统中可能会引起主备切换,危害生产环境)

GC参数
串行回收器

最古老,最稳定,效率高,可能会产生比较长的停顿

-XX:+UseSerialGC //串行回收器
  //新生代,老年代会使用串行回收
  //新生代使用的是复制算法
  //老年代使用的是标记-整理算法
并行收集器

ParNew收集器

-XX:+UseParNewGC //并行回收器
 //新生代并行,老年代串行
 //Serial收集器新生代的并行版本
 //使用复制算法
 //多线程性能比较好,需要多核支持
-XX:ParallelGCThreads //限制线程数量

parallel收集器

//类似ParNew
//新生代使用复制算法
//老年代使用标记-整理算法
//更加关注吞吐量
//串行收集器在新生代以及老年代的并行化
-XX:+UseParallelGC //新生代并行,老年代串行
-XX:+UseParallelOldGC //新生代并行,老年代并行

并行收集器其他参数

-XX:MaxGCPauseMills //最大停顿时间,单位毫秒,GC尽量保证回收时间不超过该时间
-XX:GCTimeRatio //0-100的取值范围,垃圾回收时间占总时间的比值,默认99,即允许1%时间做GC
//这两个参数是矛盾的,吞吐量和停顿时间不可能同时调优

CMS收集器

-XX:UseConcMarkSweepGC //CMS收集器,与应用程序一起并行执行,减少停顿(尽可能缩小,不能完全消除),降低吞吐量
//Concurrent Mark Sweep 并发标记清除
//使用标记-清除算法
//与标记-整理相比,并发阶段会降低吞吐量
//是老年代收集器(新生代使用PerNew)
//运行过程:
    //初始标记【停顿】(标记根可直接关联到的对象,速度快)
    //并发标记【并行】(主要标记过程,标记全部对象)
    //重新标记【停顿】(由于并发标记时,用户线程依然运行,因此正式清理前再做修正)
    //并发清除【并行】(基于标记结果,直接清理对象)
    //并发重制【并行】(为下次回收做准备)
//特点:
    //尽可能降低停顿
    //会影响系统整体吞吐量和性能
    //清理不彻底(和用户线程一起执行,会产生新的垃圾)
    //不能再空间即将满的时候再清理(如果预留空间不足,会引起concurrent mode failure,如果出现该错误,会使用[串行收集器]作为后备)
    -XX:CMSInitiatingOccupancyFraction //设置触发GC的阈值,当堆空间占用的比值达到该阈值即触发
    -XX:+UseCMSCompactAtFullCollection //full gc之后进行一次内存整理,整理期间停顿
    -XX:CMSFullGCsBeforeCompaction //设置进行几次full gc之后进行一次碎片整理
    -XX:ParallelCMSThreads //设定CMS的线程数,一般情况约为CPU数量
    -XX:+CMSClassUnoladingEnabled //允许对类的元数据进行回收
    -XX:CMSInitiatingPermOccupancyFraction //当永久区占用率达到该百分比值时,启用CMS收集器
    -XX:UseCMSInitiatingOccupancyOnly //表示只在达到阈值的时候,才进行CMS回收

G1收集器

-XX:+UseG1GC  //G1收集器
//G1(Garbage-First)是面向服务端应用的垃圾收集器。
//特点:
    //并行与并发,G1收集器可以通过并发的方式让Java程序继续执行
    //分代收集,G1可以不需要其他收集器配合就能独立管理整个GC堆,采用不同的方式去处理新创建的对象和已经存活了一段时间、熬过多次GC的旧对象以获取更好的收集效果。
    //空间整合,G1从整体来看是基于 标记—整理算法 实现的收集器,从局部来看是基于 复制算法 实现的,这两种算法都意味着G1运作期间不会产生内存空间碎片。
    //可预测的停顿,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。

//使用G1收集器时,Java堆的内存布局就与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。
-XX:G1HeapRegionSize  //设置region的大小
//G1收集器之所以能建立可预测的停顿时间模型,是因为它可以有计划地避免在整个Java堆中进行全区域的垃圾收集。G1跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region(这也就是Garbage-First名称的来由)。这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
//执行过程:
    //初始标记【停顿】(标记根可以直接关联到的对象,并修改TAMS[next top at mark start]的值),让下一阶段用户程序并发执行时,能在正确的可用Region中创建新对象
    //并发标记【并行】(标记所有对象,与用户程序并发执行)
    //最终标记【停顿】(修正在并发标记期间因用户程序继续运行而导致的标记变动)
    //筛选回收【停顿】(对各个Region的回收价值和成本进行排序,根据用户期望的停顿时间制定回收计划,这个阶段可以做到并行执行,但是只回收一部分Regina,时间是用户可控制的,停顿可以大幅提高收集效率)
-XX:InitiatingHeapOccupancyPercent  //堆内存占用达到该百分比值时启动并发GC
-XX:MaxTenuringThreshold  //提升老年代的最大临界值,默认为15
-XX:G1ReservePercent  //预留多少内存,防止晋升失败的情况,默认值是10
类加载器
class加载过程

加载-->链接(验证,准备,解析)-->初始化

加载:读取二进制文件,转换为方法区数据结构,在java堆生成对应的Class对象

链接:验证–>验证class文件格式(class文件以0xcafebabe开头),版本号是否合理,验证元数据(语法语义校验),字节码检查,符号引用验证(访问方法的权限,属性类是否存在等)

        准备-->分配内存,并为类设置初始值

        解析-->将符号引用替换为直接引用(符号替换为真实内存地址)

初始化:执行类构造器(ClassInit),赋值static变量(final变量除外)和执行静态代码块,子类初始化之前保证父类先初始化,ClassInit是线程安全的

ClassLoader

抽象类,负责类装载过程中的加载阶段,将java字节码装载到jvm中,可以定制,满足不同的字节码流获取方式

重要方法loadClass(载入并返回一个Class)、defineClass(定义一个类,不公开调用)、findClass(loadClass回调该方法,自定义时推荐重载该方法)、findLoadedClass(寻找已经加载的类)

几种类加载器:启动加载(Bootstrap ClassLoader)、扩展加载(Extension ClassLoader)、应用加载(App ClassLoader)、自定义加载(Custom ClassLoader)

除了Bootstrap外每个ClassLoader都有一个parents父类(双亲委派)

默认加载方式:自底向上检查是否已加载(Bootstrap为最上方),然后自顶向下加载类

-Xbootclasspath/a:D:/tmp/clz_dir
//指定bootstrap加载器的附加加载目录

//上下文加载器,是一个角色,用以解决顶层ClassLoader无法访问底层ClassLoader的类的问题,原理是在顶层ClassLoader中传入底层ClassLoader的实例
Thread.setContextClassLoader()

双亲模式是默认的,但不是必须这么做,如tomcat的WebAPPClassLoader就会先加载自己的class,找不到再委托parent,而不是先委托parent加载

性能监控工具

uptime(linux):系统运行时间,连接数,系统在1,5,15分钟内的平均负载

top(linux):cpu,内存使用情况

vmstat(linux):统计cpu,内存,swap(上下文切换),io等情况

pidstat(linux):(需要安装 sysstat)细致观察进程,监控cpu,io,mem,可以显示进程中的线程信息(-t参数)

perfmon(win):windows性能监控工具

process Explorer(win):系统性能监控,查看线程运行情况

pslist(win cmd):(需要安装)显示java程序的运行情况

//java 自带的监控工具
jdb            java调试工具
jhat           分析java堆
jinfo          查看正在运行的java程序的参数,支持运行时修改部分参数,-flag <name>(打印指定jvm参数值)
jmap           生成java程序的堆快照和对象的统计信息,-histo,-dump
jps            列出java进程,-q(只输出pid),-m(输出主函数参数),-l(主函数完整路径),-v(显示传递给jvm的参数)
jrunscript 		一个命令行脚本外壳
jstack         打印线程dump,-l(打印锁信息),-m(打印java和native的帧信息),-F(强制dump,当jstack没有响应时使用)

jstat			查看堆内存各部分的使用量,以及加载类的数量
jstatd		用于监控基于HotSpot的JVM中资源的创建及销毁
jConsole       图形化工具,查看java程序运行情况,监控堆信息,永久区使用情况,类加载情况等
jvisualvm      多合一的可视化监控工具,可以分析堆信息
jvm堆分析
内存溢出的原因

jvm内存中的内存区间:堆,永久区,线程栈,直接内存

堆溢出:占用大量堆空间,直接溢出(解决:增大堆空间或及时释放内存)

永久区溢出:大量的类信息导致(增大perm区,允许class回收)

栈溢出:操作系统无法为线程分配栈空间,即超过一定的线程数(每个线程独立分配一块空间),导致内存不足(解决:减少堆内存,减少线程栈大小)

直接内存溢出:操作系统无法获得足够空间,外部内存超过系统可用内存(解决:减少堆内存,有意触发gc)

MAT软件(堆分析软件)

eclipse下的软件,可在eclipse官网下载

浅堆:一个对象结构所占用的内存大小,与对象内容无关,只与对象结构有关

深堆:一个对象被gc回收后,可以真实释放的内存大小,即可以通过对象访问到的所有对象的浅堆之和

线程安全

使用锁维护程序的串行访问和安全性

对象头mark

对象头标记,32位

描述对象的hash,锁信息,垃圾回收标记,年龄

偏向锁

大部分情况是没有竞争的,所以可以通过偏向来提高性能,锁会偏向当前已经占有锁的线程,将对象头的mark标记置为偏向,并写入线程id,只要没有竞争,获得偏向锁的线程在将来进入同步块时不需要做同步,当其他线程请求相同的锁时,偏向模式结束,在竞争激烈的场合,偏向锁会增加系统负担

-XX:+UseBiasedLocking  //1.6之后默认启用
-XX:BiasedLockingStartupDelay //设置偏向锁在程序启动后的延迟时间,偏向锁在系统启动不会立马启用
轻量级锁

BasicObjectLock

轻量级锁是一种快速的锁定方法,如果对象没有被锁定,将对象头的mark指针保存到锁对象中,将对象头设置为指向锁的指针(在线程栈中),如果存在竞争,则升级为重量级锁

自旋锁

当竞争存在时,如果线程可以很快获得锁,那么可以不在系统层挂起线程,让线程做几个空操作,1.7之后为默认启用,如果同步块很长,自旋失败,会降低系统性能,如果同步块很短,自旋成功,会节省系统切换时间

锁的优化

减少锁的持有时间:缩小同步块,尽量不同步整个方法

减小锁粒度:将大对象拆成小对象,如ConcurrentHashMap,将table分为多个segment进行操作

锁分离:根据功能进行锁分离,如读写锁

锁粗化:对统一锁多次请求,同步,释放,可以将锁放大化,增加锁范围

锁消除:如果发现不可能被共享的对象,则可以消除这些对象的锁操作(-XX:+DoEscapeAnalysis(逃逸分析) -XX:+EliminateLocks(粗化锁区域))

无锁:无锁是乐观的操作,再应用层面判断多线程的干扰,如果有干扰,则重试,无锁的实现(cas(比较交换指令)),如atomic包下的类

Class文件结构
语言无关性

各种jvm语言都可以编译成class文件,运行在jvm上,并不是只有java语言,即java语言和jvm是两个分离的部分

class文件结构

u1/u2/u4表示无符号整型以及占用的字节数,文件结构如下

类型名称数量说明
u4magic1魔数
u2minor_version1小版本
u2major_version1大版本
u2const_pool_count1常量数
cp_infoconst_poolconst_pool_count-1常量
u2access_flag1访问修饰符
u2this_class1当前类,指向常量池的Class
u2super_class1父类,指向常量池的Class
u2interface_count1接口数量
u2interfacesinterface_count接口,指向常量池的Class
u2field_count1字段数量
field_infofiledsfield_count字段
u2method_count1方法数量
method_infomethodsmethod_count方法
u2attr_count1属性数量
attr_infoattrsattr_count属性

魔数magic:class文件魔数为 0xCAFEBABE

minor.major:java编译版本

常量池:支持的常用类型 (1)指向utf8的索引 (2)指向class的索引 (3)指向NameAndType的索引

描述类型结构
utf-8编码的Unicode字符串utf8tag 1,length u2,byte len
int类型的字面值Integertag 3,byte u4
float类型的字面值Floattag 4
long类型的字面值Longtag 5
double类型的字面值Doubletag 6
对一个类或接口的符号引用Classtag 7,name_index u2(1)
string类型字面值的引用Stringtag 8,string_index u2(1)
对一个字段的符号引用Fieldreftag 9,class_index u2(2),nameandtype_index u2(3)
对一个类中方法的符号引用Methodreftag 10,class_index u2(2),nameandtype_index u2(3)
对一个接口中方法的符号引用InterfaceMethodreftag 11,class_index u2(2),nameandtype_index u2(3)
对一个字段或方法的部分符号引用NameAndTypetag 12,name_index u2(1),desc_index u2(1)

类的标识符

标识value说明
ACC_PUBLIC0x0001public
ACC_FINAL0x0010final 不能被继承
ACC_SUPER0x0020是否允许使用invokespecial指令,1.2后为true
ACC_INTERFACE0x0200是否为接口
ACC_ABSTRACT0x0400抽象类
ACC_SYNTHETIC0x1000不是由用户代码生成,运行时生成,没有源码
ACC_ANNOTATION0x2000是否为注解
ACC_ENUM0x4000是否是枚举

字段标识符:access_flag

标识value描述
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_VOLATILE0x0040volatile
ACC_TRANSIENT0x0080transient
ACC_SYNTHETIC0x1000synthetic;没有源码,编译器生成
ACC_ENUM0x4000enum枚举类型

字段:常量池引用,表示字段的名字 name_index u2,descriptor_index u2

标识类型
Bbyte
Cchar
Ddouble
Ffloat
Iint
Jlong
Sshort
Zboolean
Vvoid
L对象 – Ljava/lang/Object
[数组 – [Ljava/lang/String

方法标识符:指向常量池的索引,方法描述 (args)return 如: (I)V 为 参数为int返回值空,name_index u2,descriptor_index u2

标识value描述
ACC_PUBLIC0x0001public
ACC_PRIVATE0x0002private
ACC_PROTECTED0x0004protected
ACC_STATIC0x0008static
ACC_FINAL0x0010final
ACC_SYNCHRONIZED0x0020synchronized
ACC_BRIDGE0x0040编译器产生,桥接方法
ACC_VARARGS0x0080可变参数
ACC_NATIVE0x0100native
ACC_ABSTRACT0x0400abstract
ACC_STRICT0x0800strictfp
ACC_SYNTHETIC0x1000不在源码中,编译器生成

文件属性:在field和method中,可以有若干个attr,类文件也有attr用于描述一些额外的信息,attr本身也可以包含其他的attr

attribute_name_index u2 名字,指向常量池utf8

attribute_length u4 长度

info【attribute_length】 u1 内容

名称使用者说明
Deprecatedfield method字段、方法、类被废弃,attribute_length=0
ConstantValuefieldfinal常量,attribute_length=2,constantvalue_index u2指向常量池
Codemethod方法的字节码和其他数据
Exceptionsmethod方法的异常
LineNumberTableCode_Attribute方法行号和字节码映射
LocalVaribleTableCode_Attribute方法局部变量表描述
SourceFileClass file源文件名,attribute_length=2
Syntheticfield method编译器产生的方法或字段

feild_info

–access_flags u2

–name_index u2

–descriptor_index u2

–attributes_count u2

–attribute_info  attributes [attributes_count];

method_info

–access_flags  u2

–name_index  u2

–descriptor_index u2

–attributes_count  u2

–attribute_info  attributes [attributes_count];

sourceFile

–attribute_name_index u2

–attribute_length u4(固定为2)

–soucefile_index u2(UTF-8常量索引)

exception

–attribute_name_index  u2

–attribute_length  u4

–number_of_exceptions  u2

–exception_index_table [number_of_exceptions] u2(指向Constant_Class的索引)

LocalVariableTable

LocalVariableTable_attribute {

	u2 attribute_name_index;
	
	u4 attribute_length;
	
	u2 local_variable_table_length;
	
	{ 
		u2 start_pc;
		
		u2 length;
		
		u2 name_index;
		
		u2 descriptor_index;
		
		u2 index;
	
	} local_variable_table [local_variable_table_length];

}

LineNumberTable

LineNumberTable_attribute {

	u2 attribute_name_index;
	
	u4 attribute_length;
	
	u2 line_number_table_length;
	
	{ 
		u2 start_pc;
		
		u2 line_number;
	
	} line_number_table [line_number_table_length];

}

code

Code_attribute {

	u2 attribute_name_index;
	
	u4 attribute_length;
	
	u2 max_stack;
	
	u2 max_locals;
	
	u4 code_length;
	
	 u1 code [code_length];
	
	u2 exception_table_length;
	
	{ 
		u2 start_pc;
		
		u2 end_pc;
		
		u2 handler_pc;
		
		u2 catch_type;
	
	} exception_table [exception_table_length];
	
	u2 attributes_count;
	
	attribute_info attributes [attributes_count];

}
字节码的执行
javap //JDK自带的反汇编器

jit:just in time 将执行比较频繁的代码编译成机器码,-XX:CompileThreshold=100(设定jit阈值),-XX:+PrintCompilation(打印编译信息)


其他说明

(1)dump:在特定时刻,将整个储存装置或储存装置之某部分的内容记录在另一储存装置中

(2)新生代GC(Minor GC):指发生在新生代的垃圾收集动作,因为Java对象大多都具备朝生夕灭的特性,所以Minor GC非常频繁,一般回收速度也比较快

(3)老年代GC(Major GC / Full GC):指发生在老年代的GC,出现了Major GC,经常会伴随至少一次的Minor GC(但非绝对的,在Parallel Scavenge收集器的收集策略里就有直接进行Major GC的策略选择过程)。Major GC的速度一般会比Minor GC慢10倍以上。

(4)吞吐量:吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码时间 /(运行用户代码时间 + 垃圾收集时间)。

(5)Region:G1默认把堆内存分为1024个分区,后续垃圾收集的单位都是以Region为单位的。Region是实现G1算法的基础,每个Region的大小相等,通过-XX:G1HeapRegionSize参数可以设置Region的大小。

同类文章 https://www.cnblogs.com/yxwkf/p/5222589.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值