『编程』12000字 史上最最最完整深入解析JVM,请先收藏再看!( 六 )


4、设置最小堆和最大堆:-Xmx和-Xms稳定的堆大小堆垃圾回收是有利的 , 获得一个稳定的堆大小的方法是设置-Xms和-Xmx的值一样 , 即最大堆和最小堆一样 , 如果这样子设置 , 系统在运行时堆大小理论上是恒定的 , 稳定的堆空间可以减少GC次数 , 因此 , 很多服务端都会将这两个参数设置为一样的数值 。 稳定的堆大小虽然减少GC次数 , 但是增加每次GC的时间 , 因为每次GC要把堆的大小维持在一个区间内 。
5、一个不稳定的堆并非毫无用处 。 在系统不需要使用大内存的时候 , 压缩堆空间 , 使得GC每次应对一个较小的堆空间 , 加快单次GC次数 。 基于这种考虑 , JVM提供两个参数 , 用于压缩和扩展堆空间 。 (1)-XX:MinHeapFreeRatio 参数用于设置堆空间的最小空闲比率 。 默认值是40 , 当堆空间的空闲内存比率小于40 , JVM便会扩展堆空间(2)-XX:MaxHeapFreeRatio 参数用于设置堆空间的最大空闲比率 。 默认值是70 ,当堆空间的空闲内存比率大于70 , JVM便会压缩堆空间 。 (3)当-Xmx和-Xmx相等时 , 上面两个参数无效
6、通过增大吞吐量提高系统性能 , 可以通过设置并行垃圾回收收集器 。 (1)-XX:+UseParallelGC:年轻代使用并行垃圾回收收集器 。 这是一个关注吞吐量的收集器 , 可以尽可能的减少垃圾回收时间 。 (2)-XX:+UseParallelOldGC:设置老年代使用并行垃圾回收收集器 。
7、尝试使用大的内存分页:使用大的内存分页增加CPU的内存寻址能力 , 从而系统的性能 。 -XX:+LargePageSizeInBytes 设置内存页的大小
8、使用非占用的垃圾收集器 。 -XX:+UseConcMarkSweepGC老年代使用CMS收集器降低停顿 。
9、-XXSurvivorRatio=3 , 表示年轻代中的分配比率:survivor:eden = 2:3
10、JVM性能调优的工具:(1)jps(Java Process Status):输出JVM中运行的进程状态信息(现在一般使用jconsole)(2)jstack:查看java进程内线程的堆栈信息 。 (3)jmap:用于生成堆转存快照(4)jhat:用于分析jmap生成的堆转存快照(一般不推荐使用 , 而是使用Ecplise Memory Analyzer)(3)jstat是JVM统计监测工具 。 可以用来显示垃圾回收信息、类加载信息、新生代统计信息等 。 (4)VisualVM:故障处理工具
类加载机制:一、 概念:类加载器把class文件中的二进制数据读入到内存中 , 存放在方法区 , 然后在堆区创建一个java.lang.Class对象 , 用来封装类在方法区内的数据结构 。 类加载的步骤如下:
1、加载:查找并加载类的二进制数据(把class文件里面的信息加载到内存里面)
2、连接:把内存中类的二进制数据合并到虚拟机的运行时环境中(1)验证:确保被加载的类的正确性 。 包括:
A、类文件的结构检查:检查是否满足Java类文件的固定格式   B、语义检查:确保类本身符合Java的语法规范   C、字节码验证:确保字节码流可以被Java虚拟机安全的执行 。 字节码流是操作码组成的序列 。 每一个操作码后面都会跟着一个或者多个操作数 。 字节码检查这个步骤会检查每一个操作码是否合法 。  D、二进制兼容性验证:确保相互引用的类之间是协调一致的 。

(2)准备:为类的静态变量分配内存 , 并将其初始化为默认值(3)解析:把类中的符号引用转化为直接引用(比如说方法的符号引用 , 是有方法名和相关描述符组成 , 在解析阶段 , JVM把符号引用替换成一个指针 , 这个指针就是直接引用 , 它指向该类的该方法在方法区中的内存位置)
3、初始化:为类的静态变量赋予正确的初始值 。 当静态变量的等号右边的值是一个常量表达式时 , 不会调用static代码块进行初始化 。 只有等号右边的值是一个运行时运算出来的值 , 才会调用static初始化 。
二、双亲委派模型:
1、当一个类加载器收到类加载请求的时候 , 它首先不会自己去加载这个类的信息 , 而是把该 请求转发给父类加载器 , 依次向上 。 所以所有的类加载请求都会被传递到父类加载器中 , 只有当父类加载器中无法加载到所需的类 , 子类加载器才会自己尝试去加载该类 。 当当前类加载器和所有父类加载器都无法加载该类时 , 抛出ClassNotFindException异常 。