Chen Jian

学习JVM原理-9.ByteCode文件结构概述

摘自《深入理解Java虚拟机》周志明著 ByteCode类文件   1. 二进制文件   2. 以字节为单位存放有意义的数据,不以0/1为单位(怪不得叫字节码?)   3. 某段数据的意义由它所处的位置来定,并不像XML或JSON一样有元数据,如<name>abc</name>,ByteCode文件里只有"abc" 数据结构的范式(把一个类文件看作一栋楼)      1. 砖头: 无符号数     2. 房间: Table, 由无符号数搭建而成     3. Table下可以有Table     4. 整个类文件就是一个Table 主要数据成员:   1.Magic Number,表明当前文件是Class文件(固定为0xCAFEBABE)   2.minor_version 和 major_version,这决定了本class可以被什么版本的JRE运行   3.constant pool   4.access_flags, this_class,super_class, interfaces等   5.fields, methods   6.attributes,如字节码指令,exceptions,line number等

学习JVM原理-8.一个GC调优的实例

这个例子算是《深入理解Java虚拟机》第5章中某个例子的简写版。 1. 症状:系统启动比较慢,可能跟GC不力有关 2. 诊断:通过 打印GC日志,看看有没有什么不正常   a.为了打印GC日志,系统启动时加上三个JVM参数:     -XX:+PrintGCTimeStamps     -XX:+PrintGCDetails     -verbose:gc   b.启动系统,得到GC日志,这时可以重点关注Full GC,因为Full GC的时间比Minor GC长的多: 16.400: [Full GC 16.400: [Tenured: 53K->8872K(87424K), 0.5714300 secs] 26375K->8872K(126720K), [Perm : 16384K->16384K( 16384K)], 0.5715650 secs] [Times: user=0.26 sys=0.01, real=0.58 secs] 20.159: [Full GC 20.159: [Tenured: 8872K->10445K(87424K), 0.3710940 secs] 18205K->10445K(126848K), [Perm : 20479K->20479K( 20480K)], 0.3711840 secs] [Times: user=0.27 sys=0.00, real=0.38 …

学习JVM原理-8.一个GC调优的实例 Read More »

学习JVM原理-Direct Memory只会在Full GC时回收

摘自《深入理解Java虚拟机》周志明著 Direct Memory满了之后,系统不会自动回收这段内存; 而是要等Tenured Generation满触发GC时,Direct Memory才会被跟着回收。 所以这一块很容易发生内存溢出. 为了防止这种事发生,你要么不把Heap设的过多,该Full GC的时候就Full GC; 要么在JVM参数里不禁止System.gc(),因为NIO的实现里会自己调用System.gc()

学习JVM原理-Heap并不是越大越好

Heap越大,意味着里面可以放的对象越多,一旦发生Full GC,停顿会很长 Heap如果特别大,一旦发生内存溢出,生成Dump的就会非常大,大到几乎无法分析 周志明说:“给JVM分配超大堆的前提是有把握把应用程序的Full GC频率控制得足够低,并且保证程序足够稳定,不会产生堆溢出“

学习JVM原理-7.JVM监控工具

摘自《深入理解Java虚拟机》周志明著 1.jdk自带的文字界面工具 a. jps, 查看所有JAVA进程列表: jps -lvm b. jstat, 统计信息监控,如内存、GC等,如jstat -gcutil pid c.查看虚拟机的各项参数: sudo jinfo -flags pid d.打印System.getProperties(): sudo jinfo -sysprops  pid e. jmap, 查看Memory映像: jmap -dump:forbmat=b, file=dump.bin pid (dump.bin这个文件可以用Eclipse Memory Analyzer)来分析 f. jstack,生成线程快照,查找线程停顿原因的利器:sudo jstack -l -F  pid 2.Oracle/Sun提供的可视化工具 a. JConsole,通过JMX进行监控 (path: jdk/bin/jconsole) b. VisualVM,什么都可以做,而且可以直接应用在生产环境中,因为它不需要被监控的系统打开任何监控接口(但要在同一台机上另建一个基于rmi的jstatd服务) (path: jdk/bin/jvisualvm)

关于System.gc()

javadoc说: Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects in order to make the memory they currently occupy available for quick reuse. When control returns from the method call, the Java Virtual Machine has made a best effort to reclaim space from all discarded objects.   注意,只是“建议”JVM干这样一种事,不是直接命令 …

关于System.gc() Read More »

Hotspot中的Permanent Generation

Permanent Generation跟Young Generation, Tenured Generation不是一个层次的概念,Young和Tenured是指Heap内部的划分,而Permanent Generation其实就是规范里的Method Area

学习JVM原理-6.HotSpot支持的垃圾回收器

摘自《深入理解Java虚拟机》周志明著 垃圾回收器是GC算法在虚拟机中的具体实现。 HotSpot针对Young Generation和Tenured Generation分别提供了一些回收器,你可以按照你的系统要求来选取合适的组合, 考量因素包括:服务端系统还是客户端系统,追求用户体验还是希望不浪费CPU空间等 HotSpot提供的回收器:   1. Young Generation: Serial,  ParNew, Parallel Scavenge   2. Old Generation: Serial Old, CMS, Parallel Old Serial和Serial Old在GC时会停止其他工作线程(术语: Stop the world),这样回收效率最高,但代价是用户可能要容忍长时间的停顿;这个组合是Client模式下的默认选项,因为Client模式下一次性需要回收的内存并不大,虽然GC时会有停顿,但停顿时间一般会在一百毫秒以内 ParNew是高版本的Serial,它照样会Stop the world,只不过在多CPU环境下它的表现更好 Parallel Scavenge + Parallel Old组合的目标是为了尽最大可能把CPU精力放在工作上,而不是放在GC上(术语:吞吐率高);它适于在后台运算而不太需要太多交互的任务 CMS(Concurrent Mark Sweep)模式下,GC线程与工作线程同时工作,虽然有时也需Stop the world,但这个停顿时间非常短,因此 CMS模式适用于用户交互的系统,如互联网。 但CMS也有它的缺点:   a.与工作线程并发工作,因此对CPU的并发性要求比较高,最好用在多核(>= 4)的系统中,否则可能得不偿失   b.由于GC的过程中工作线程会产生新的垃圾(floating garbage), 如果等内存塞满了才开始GC,这些新的垃圾就没地方放,所以必须在塞满前就开始GC; 这可能导致GC的频率比较高,更严重的是,如果floating garbage的大小超过了当前所能容纳的空间,JVM会启动一次Full GC(基于Serial Old),这样的停顿时间就很长了。 …

学习JVM原理-6.HotSpot支持的垃圾回收器 Read More »

学习JVM原理-5.Young Generation和Tenured Generation

摘自《深入理解Java虚拟机》周志明著 GC的算法不止一种,不同的对象适用不同的算法。 因此JVM对内存进行了分区,不同区域适用不同算法。 一般分作Young Generation和Tenured Generation两个区域   1. Young Generation一般用Copying算法,但空闲部分只设10%(因为研究表明GC时大部分对象都会被杀);存活对象转移时,如果空闲部分不够装,则把装不下的放到Tenured Generation中(参见Eden, Survivor等术语)   2. Tenured Generation用来装Young Generation中转移过来的对象(在Young Generatioin中经历了足够多次GC,或者Young Generation中已放不下),已及一些不方便放在Young Generation中的对象,如大对象等。 Tenured Generation一般用Mark-Sweep算法或其改良版      Young Generation可以再分为 两部分: Young generation memory consists of two parts, Eden space and survivor space. Shortlived objects will be available in Eden space. Every object starts its life from Eden space. When …

学习JVM原理-5.Young Generation和Tenured Generation Read More »

学习JVM原理-4.GC算法:批量处理还是一个一个处理

摘自《深入理解Java虚拟机》周志明著 答案:批量处理 具体有两种做法:   1.Mark(判死刑),然后批量sweep (Mark-Sweep算法)   2.把所有对象都放到Heap中的一块区域中,这个区域可以理解为一个监狱;监狱塞满人时,就一次性找出尚不须回收的对象,把它们复制到Heap中的空闲区域中,然后投弹夷平监狱,清除出整个内存区域;新的关押区域即成新的监狱,它也终将被夷平 (整个算法叫做copying 算法) 第一种做法中,由于存活对象跟可回收对象混杂在一起,可回收对象们没有集中在一起,因此要一个一个清除,效率会比较低(相当于挨家挨户搜查杀人),而且还会造成内存碎片,不利于大对象的分配 第二种模式效率高,且没有内存碎片,但由于它总是用一块内存,空置一块内存,这会造成内存浪费。