JVM概述
JVM概述
图样图森破 发表于1年前
JVM概述
  • 发表于 1年前
  • 阅读 7
  • 收藏 1
  • 点赞 0
  • 评论 0

腾讯云 新注册用户 域名抢购1元起>>>   

1.1  JVM模式

Jvm分为client模式和server模式[在开发端使用什么模式有待商榷],两者的区别为:server模式启动速度慢(启动速度慢10%),运行之后效率高很多,client模式运行的代码可能会在server模式中出错。[此问题未找到明确的资料

Debugging tip: 

    For server applications, be sure to always specify the -server JVM command line switch when invoking the JVM, even for development and testing. The server JVM performs more optimization than the client JVM, such as hoisting variables out of a loop that are not modified in the loop; code that might appear to work in the development environment (client JVM) can break in the deployment environment (server JVM). For example, had we "forgotten" to declare the variable asleep as volatile in Listing 3.4, the server JVM could hoist the test out of the loop (turning it into an infinite loop), but the client JVM would not. An infinite loop that shows up in development is far less costly than one that only shows up in production.]

可以通过 java -version命令查看当前jvm的模式。

 

 

切换JVM的client和server模式:

修改jvm.cfg文件来进行调整JVM模式,

32位系统文件目录:JAVA_HOME/jre/lib/i386/jvm.cfg

64位系统文件目录:JAVA_HOME/jre/lib/amd64/jvm.cfg

 

切换方法:

“-server KNOWN”与”-client KNOWN”两个参数在前面的为JVM的当前模式,切换前必须保证JAVA_HOME/jre/bin目录下存在server和client两个文件夹。

 

1.2    JVM模型

JVM内存模型如下图:

 

1:程序计数器

当前线程所执行的字节码的行号指示器;

线程私有(每个线程分配一个);

字节码解释器工作时通过改变这个计数器的值来选取下一条需要执行的字节码指令,分之、循环、跳转、异常处理、线程回复等基础功能都需要依赖它完成;

唯一不会出现OOM的区域。

2:虚拟机栈

线程私有,生命周期与线程相同

每个方法执行的时候都会生成一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等,当前方法执行完成之后,该方法对应的栈帧就会出栈,栈的执行顺序为先进后出。

3:本地方法栈

与虚拟机栈相似,运行本地方法,hotspot中将本地方法和虚拟机栈合二为一。

4:堆

线程共享;

几乎所有的对象实例及数组都需要在堆上分配,其中还有线程私有的分配缓冲区[],在物理内存中处于不连续的内存空间中。

5:方法区

线程共享;

存储已被JVM加载的类信息、常量、静态变量、即时编译器、编译后的代码等数据,HotSpot将该区与堆一起管理,成为持久代。

6:运行时常量池

此内存空间是方法区的一部分,存放编译器生成的各种字面量和符号引用,常量池将在类加载后进入方法区的运行时常量池中存放。

7:直接内存

直接内存不是JVM运行时数据区的一部分,也不是JVM规范中定义的内存区域,为了避免NIO在java堆和native堆中来回复制数据,才使用该内存空间。

 

1.3    JVM垃圾回收器

1:Serial收集器

单线程收集器,每次回收都会停止其他工作线程,client模式下新生代默认收集器,相比于其他单线程收集器相比效率很高。

新生代采用复制算法,老年代采用标记整理算法。

2:ParNew收集器

是Serial收集器的多线程版本,每次回收都会停止其他工作线程,只是GC线程为多个,server模式下新生代推荐使用的收集器,也是唯一一个可以和CMS收集器配合工作的收集器。

新生代采用复制算法,老年代采用标记整理算法。

3:Parallel Scavenge收集器

用于新生代,使用复制算法、并行[1并行:只多条垃圾收集线程并行工作,工作线程停在安全区域。

2并发:垃圾回收线程与工作线程同时进行,不会出现stop the world。]多线程的收集器。

此收集器关注点为吞吐量[吞吐量=程序运行时间/(程序运行时间+GC时间)]优先,并可以通过-XX:MaxGCPauseMillis参数控制最大垃圾收集停顿时间,通过-XX:GCTimeRatio参数控制吞吐量。还可以通过-XX:+UseAdaptiveSizePolicy参数让收集器自动控制新生代大小、Eden与Survivor区的比例、晋升老年代的对象年龄(自适应调节,这也是和ParNew收集器的重要区别)。

4:Serial Old收集器

是Serial收集器的老年代版本,单线程,使用标记整理整理算法,主要用于client模式下的JVM,当并发收集器发生Concurrent Mode Failure[]时备用该收集器。

5:Parallel Old收集器

Parallel Scavenge收集器的老年代版本。使用多线程和标记整理算法。

6:CMS收集器

这是一种获取最短回收停顿时间为目标的收集器,使用并发收集、标记清除算法。目前主流的收集器。

1.4 JVM回收算法

1: 标记清理算法:标记和清理两个过程效率都不高,并且会在内存中产生大量的碎片,以至于当大对象进入内存时无法进行分配足够的连续内存空间。

2:复制算法:由于年轻代垃圾回收率非常高(超过80%,甚至更高),将年轻带分为成一个较大的Eden空间和两个较小的Survivor空间,每次使用Eden和一个Survivor空间,当进行GC时,将这个区域中有用的对象复制到另外一个Survivor空间中,默认情况下Eden空间和Survivor空间的比例为8:1,当Survivor空间不足的时候会向老年代申请分配担保。

3:标记整理算法:将可回收对象标记并清理,清理完成之后,将存活的对象移动到内存的一端。

4:分代收集算法:将java堆分为年轻代与老年代,每个年代使用最合适的收集算法。由于年轻代大部分对象的生命周期非常短,所以使用复制算法;由于老年代对象存活率高、没有额外的担保空间,所以使用标记清理或者标记整理算法。

1.5 对象进入老年代

1:新生代对象每次进行一次GC,存活的对象年龄都会加1,当对象年轻到达指定值(HotSpot默认情况下为15)时会被转移到老年代。

2:如果年轻带中Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,年龄大于等于该年龄的对象就可以直接进入老年代。

3:当进行MinorGC时,存活对象大于Servivor空间,则在老年代中进行担保。若老年代中空间不足则进行FullGC(majorGC)。

2.1 JVM参数

Xms : 初始堆大小

Xmx : 堆最大扩展大小

Xmn : 年轻代大小

-XX:PermSize : 持久代大小

-XX:MaxPermSize : 持久代扩展大小

Xss : 线程栈大小,默认1M

-XX:NewRatio : 年轻代与老年代的比值,Xms=Xmx且定义了Xmn的情况下不用设置

-XX:SurvivorRatio : Eden和Survivor大小比值,默认为8

-XX:+AggressiveOpts : 加快编译,jdk5 update6添加,1.6默认开启

-Xverify:none  禁止字节码验证过程

-server 使用server模式jvm

-client 使用client模式jvm

共有 人打赏支持
粉丝 4
博文 28
码字总数 16198
×
图样图森破
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: