虚拟机调优详解
在黑窗口中输入 java -version 会出现三行代码
- Java版本号
- Java信息(是企业级还是什么的)
- Java 的核心组件 hotsport client vm,热点探测,对class文件做标记,对频繁编译的class文件当达到一定阈值直接生成本地代码(1.5版本及之后才有)。
一个系统分配了两个版本,一个是server一个是client,client内存小可能就几百M,根据运行的项目大小来分配用哪个版本。
具体修改是在java的lib目录下有个i380的文件打开之后有个java.cig文件,打开之后看下边的代码,-server和-client哪个在上边就是用的哪个,修改的话需要管理员权限才可以更改。
虚拟机的分块:
1. 类加载子系统:
类加载负责从文件中或网络中加载class信息。加载的类信息存放为方法区的内存空去,还有运行时的常量池,字符串,字面量和数字常量。
2. Java堆:
在java虚拟机启动时创建的,是主要的内存工作区域,java对象实例存放,堆空间是所有线程共享的。
3. 直接内存:
直接映射物理内存的,不受jvm空间限制,取决于物理内存,提高运行小路的。
4. 垃圾回收系统:
垃圾回收器可以对方法区、Java堆和直接内存进行回收。Java堆是垃圾回收的重点工作。
5. Java栈:
每个java虚拟机线程都有一个私有的java栈,一个线程的java栈在线程创建的时候创建,保存着帧信息。保存着局部变量、方法参数,同时和java的方法调用和返回密切相关。
6. 本地方法栈:
本地方法栈和java栈类似,最大的不同在于本地方法栈用于本地方法的调用,调用操作系统的api,一般都是c语言编写的。
7. Pc寄存器:
Pc寄存器也是每一个线程私有空间,每个线程一个pc寄存器,区分线程的执行方法使本地方法还是java方法。
8. 执行引擎:
负责执行虚拟机的字节码,提高执行效率,会使用即时编译技术将方法编译成机器码后执行。
Java堆结构图及分代
根据对象存活的周期不同分为新生代、老年代和永久代。
是垃圾回收最频繁的一块区域,根据周期来区分垃圾回收。区域划分有利于垃圾回收。影响我们的gc效率。
创建对象会分配到新生代中,经过多次回收仍然存活下来的会放到老年代空间中,老年代一般很少做回收,一般永久代存放静态属性,类信息等。
永久代是hotsport虚拟机特有的概念,1.7已经开始“去永久代”的。
堆有5块区域:
创建对象是在eden里边的,这里边也是绝大多数都要回收掉的,剩下的在保存到from和to中,做进一步处理。
上图的新声代的内存默认占比是8:1:1,在eden中的回收率在70%-95%左右。但是创建的大对象会存放到老年代中。
Minor GC原理:
在eden中创建的对象使用过后,幸存下来的赋值到from区,当阈值达到15次还存活的就赋值到to区,将from区清空,在to区再有个阈值还存活的就保存到老年代中,to区清空。
垃圾回收算法:
1. 引用计数法:
此对象有一个引用,增加一个计数,删除一个引用则减少一个计数。当计数为0时就表明没有指向引用,可以回收。
缺点:没办法解决循环引用的问题。
2. 复制算法:
把内存空间划分为两个相等的区域,每次只使用其中一个区域,垃圾回收是,遍历当前使用区域,把正在使用的对象复制到另外一个区域中,每次只处理正在使用的对象,因此复制成本较小,复制过去后还能进行相应的内存整理,不会产生垃圾“碎片”。
缺点:要两倍的内存空间。
3. 标记清除:(最古老的基础)
此算法执行两个阶段,第一阶段从引用根节点开始标记所有的引用对象,第二剪短遍历整个堆,把未标记的对象清除。
缺点:暂停应用,产生碎片。
4. 标记整理:(结合了标记清除和复制)
有两个阶段一个阶段是从根节点开始标记多有被引用的对象,第二节点遍历整个堆,把清除未标记对象并且把存活的对象“压缩”到堆得其中一块,安顺序排放,此算法避免了标记清除的碎片问题也避免了复制的空间问题。
垃圾收集器:
次收集和全收集
次收集影响的是新生代的eden区,当eden空间不足以为对象分配内存是会触发次收集。
当新生对象生成,并且把尚且存活的对象移动到fron或者to区,然后整理这两个区,不影响老年代,
老年代GC(全收集),是发生在老年代的,当全收集触发是肯定是有多次次收集的。全收集比次minor GC慢10倍,当老年代内存不足或者显示调用System.gc()方法时会触发。
Hotsport的7个分代收集器:
Java中的jps.exe来做虚拟机的显示灯功能的(jvm的小程序)。
Jps -l :显示当前系统正在运行的虚拟机的线程id。
Jps -v:除了显示运行的线程id以外的其它信息。
执行jstat -gc 端口号 输出时间 条数
如 jstat -gc 8008 250 20
输出的结果如:
S0C (S0创建大小字节)
S1C(S1创建大小字节)
S0U(S0用的时间毫秒)
S1U(S1用的时间毫秒)
EC (新生代的eden创建的大小)
EU (新生代的eden创建的时间)
OC (老年代的创建空间)
OU(老年代的创建时间)
PC (持久代的创建大小空间)
PU (持久代的创建大小时间)
YGC (新生代次收集器收集的次数)
YGCT (新生代次收集器收集的时间)
FGC (全收集器收集的次数)
FGCT (全收集器收集的时间)
GCT (次收集器和全收集器的总时间)
Jvisualvm:强大的工具,图形化界面展示信息。
运行之后显示:
里边有当前运行的线程,双击之后打开,详细信息更全,一览无余。
Eclipse调优:
安装jvisualvm Visual GC插件 在浏览器查出github的网站自己下载。
文件是下边这个:
在已下载的里边添加下载的文件,nbm的文件。
像jps.txt等的执行命令之所以很小是因为里边只保存了相关启动程序的启动类,启动的具体内容都在这个tools这个文件里。重启jvisualvm。
安装成功重启之后。
JVM常见参数:
堆设置:
Jvm中最大的对大小有三方面的限制:
1, 操作系统的数据模型(是32的还是64的)
2, 系统的可用虚拟内存限制
3, 线程的可用物理内存限制
32位的一般限制在1.5G~2G,64位的理论上可以无限,但是这个要根据物理内存而定,不能超过物理内存的4.2%左右(大概的不准)。
典型设置:
吞吐量优先的并行收集器:
调优总结: