存放指令位置。
每个线程对应一个栈,每个方法对应一个栈帧。栈帧包含:局部变量表,操作数栈,动态链接,方法出口。非static方法需要一个对象this。dup会在栈里原来的指针上面新加个指针,同时指向堆里的一块区域,当执行invokespecial的时候,会弹出复制的那个指针执行构造方法,把对象赋初始值。字节码指令中假如没有上两个步骤则证明2占字节数太多。
java1.4之后增加了一个Direct Memory,jvm直接访问内核空间,NIO,提高效率,实现zore copy。
运行c++方法
包括新生代+老年代
1.8之前用的是perm space(永久代)实现,大小启动的时候指定,不能变,FGC不会清理,1.8及之后用的是meta space,不设定就是最大物理内存,会触发FGC清理。如何确定1.7字符串常量位于perm还是堆,一直创建就行。1.7之前运行时常量池位于方法区,1.8之后再堆里。
i=i++的运算。
基于栈。基于寄存器,hotspot的局部变量表类似于寄存器。赋值store,压栈load。invoke:invokeStatic,调用静态方法。invokeVirtual:多态,final,非静态。ArrayList l=new ArrayList;l.add(“2”)。invokeSpecial,可以直接定位的,不需要多态的方法。invokeinterface(上面的例子)。invokedynamic,lamada,或者反射。
怎么寻找垃圾:reference count(引用计数)。root searching(跟可达)。跟对象:线程栈变量,静态变量,常量池,JNI指针。
GC算法:标记清除(MARK SWEEP):两遍扫描,效率低,容易产生碎片,适合存活对象高的情况,不适合伊甸园区,适合老年代。标记整理/压缩(Mark Compat):效率更低,老年代,两遍扫描。复制算法(copy):空间浪费,对象移动,指针引用调整,扫描一次,效率高,适合伊甸园区,新生代。
ZGC之前所有的垃圾回收都是分代的,SD之前不分代。
说明:除了Epsilon,ZGC,shenandoah之外的都是逻辑分代;G1是逻辑分代,物理不分代。新对象刚创建会在栈上分配。新生代YGC,MinorGC;老年代fullgc,majorgc。新生代包含(伊甸园区和servior from 和servior to 比例8:1:1):老年代=1:2。参数查询:java-XX:+printFlagfinal-version |grep xxx。zing就一个参数。目前没有不产生STW的垃圾回收器。jdk诞生就伴随着serial,为了提高效率诞生了PS;为了配合CMS,诞生了PN;CMS是1.4版本后期引入的,是里程碑式的GC,开启了并发回收,目前没有任何一个jdk版本,默认都是CMS;jdk8默认值parallel,jdk9默认是G1.java -XX:+printflagdfinal-version |grep NEWratio查看年轻代老年代比例,额外newsize。分区概念:内存泄漏memory leak,内存溢出out of memory。lambda会导致方法区溢出,-xss。C++回收内存,析构函数;重写finalize,每个finalize耗时200ms。如果有一个系统,内存一直消耗不超过10%,但是观察GC日志,发现FGC总是频繁产生,会是什么引起的,system.gc()(这个比较low)。-XX:+disableexplictGC system.gc()不管用,FGC.
SERIAL:stop the world(STW),线程停止安全点(safe point),单线程。
serial old:STW,单线程。
parnew:stw,ps的变种。
CMS:初始标记(只标记根,stw,单线程),并发标记(非根),重新标记(stw,标记并发标记过程的垃圾,多线程),并发清理(浮动垃圾)。缺点:CMS不行了,serial会上场。folating garbage(并发清理过程产生的垃圾),concurrent mode failure,降低触发cms阈值-xx:cmsinitatingOccupancyfraction
原来是68%,1.8成了92%,可以降低改成70%,越低内存浪费越多,降低保持老年代有足够的空间,promotionfailed。碎片化。
算法:三色标记+incremental update(增量更新,关注引用的增加a->d,把黑色重新标记为灰色,下次重新扫描)
parallel old(pc):stw,默认环境回收期,多线程。
parallel old(po):同上。
G1(10MS):1.7,1.8稳定,任然有YGC(STW)FGC概念。算法:三色标记+satb(snaphot at the beginning,关注引用的删除,当b->d消失时,把这个引用推到gc的栈,保证d还能被gc扫描到)。garbage first。特点:并发标记,并发回收,压缩空闲时间,不回延长gc的暂停时间,预测gc暂停时间,适合不需要实现很高吞吐量的场景。
ZGC(1MS):算法:颜色指针(colored pointers)+写屏障。pk c++。至少11,jdk13.
shenandoah:算法:颜色指针(colored pointers)+读屏障。
epsilon:debug。
内存对应:serial几十M。ps上百M-几个G.cms20G。G1上百g 。zgc 4t-16t。
垃圾回收器参数:-xx:+useserialGC=serial new +serial old.-xx:+userparnewgc=parnew +serial old.-xx:+useconcurrent marksweepgc=par new +cms+serial old.-xx:+useparallel(old)gc=ps+po.-xx:+userg1gc=g1.
heapdump:eden space 563k,94% used[0x000000000ff980000,0x00000000ffeb29,0x000000000000ffff0000]后面的内存地址指的是起始地址没使用空间结束地址没整体空间结束地址。
对象内存分配:线程本地分配(TLAB),占用eden,默认1%,多线程不用争用eden就可以申请资源提高效率,小对象。-xx:+doescapeanalysis-xx:+eliminateallocations -xx:+usetlab 关闭逃逸分析,栈上分配。对象何时进入老年代-xx:maxtenuringthreshold,ps 15 ,CMS 6 g1 15.动态年龄。分配担保:YGC期间,servior空间不够了直接进去老年代。
概念:吞吐量:用户代码时间/(用户代码+垃圾回收),例ps+po,响应时间:stw越短,相应越好。同步消除:如果对象没有出现线程逃逸,那该对象的读写就不会存在资源的竞争,不存在资源的竞争则可以消除对该对象的同步锁。
日志参数:1 -xloggc:/opt/xxx/log/xxx-XXX-gc-%t.log
-xx:+usergclogfilerotation.-xx:numberofgclogfile=5.-xxgclogfilesize=200M-xx:+printgcdetails.-xx:+printgcdatestampsps-xx:+printgccause 2或者每天产生一个日志文件。
调优步骤:top ,top -hp【pid】。jinfo【pid】进程号,虚拟机详细信息,一般不用。jmap -histo【pid】|head -20,1 heapdump,oom的时候会自动产生堆转储文件-xx:+heapdumponoutofmemoryerror -XX:heapdumppath=user/local/base。2 很多服务器备份,停掉这台服务器,对其他没影响。 3在线工具(cmddline arthas)4 jmap -dump:format=b,file=xxx.pid–线上系统jmap期间会对线程产生很大影响,甚至卡顿(用前三种)额外:jcmapgc,heap_dump d:\dump\heap.hprof。jstack纤程情况,waiting,blocking。jstat-gc【pid】500(每500毫秒打印一次),一般不用。jconsole。jvisualvm使用jmx,jmx对性能有影响。jprofiler(最好用)。非可视化工具cmdline arthas.使用mat/jhat/jvisualvm进行dump文件分析。jhat-j-mx512 xxx.dump,拉到最后找到对应连接可以使用oql查找定位问题对象。
参数:java-xx:+printCommandlineflags hellogc等
arthas。
程序运行就是进程,进程可以有很多线程,线程可以有纤程。用户态叫做纤程,切换轻;内核态叫线程,切换重。纤程启动的数量比线程多。jdk14都没看到纤程影子。
CMS G1
说明:G1与PS相比吞吐量降低了10%-15%,但是响应时间200ms。软件架构核心思想:分而治之,分层。
G1基础概念:G1把内存分为每一块一块的区域(1m-32m),包含:surivor eden old humongos。card table(只有一个):由于做YGC时,需要扫描整个old区,效率非常低,所以jvm设计了cardtable,如果一个old区cardtable中有对象指向Y区,就将它设为dirty,下次扫描时,只需扫描dirty card在结构上,cardtable用bitmap来实现,Y区不用标记。collectionset:被回收的card装到一个表里。rememberset:每个region里面都有个表格,记录着其他region到本region的引用,详细到对象级别,占region的10%,由于rset的存在,每次给对象赋引用的时候就会做一些额外的操作,在rset中做额外的记录。这个叫做GC的写屏障。新老年代动态,不用指定,新生代一般为5-60%。G1对象分配不了,就会产生fullgc,扩内存,提高cpu性能,降低mixedgc发生的阈值,默认45%。mixedgc相当于一个cms,回收region不分年轻代还是老年代-xx:initatingheapoccupancy percent=xxx默认45%
YGC(eden空间不足,多线程并行执行)FGC(system.gc,old空间不足)。并行筛选回收,复制顺带压缩。
三色标记:白色:未被回收;黑色:自己的孩子都被标记;灰色:自己被标记,孩子没有被标记。漏标 (本来是live object,但是由于没有被遍历所以被回收),黑色指向了白色,灰色指向的白色的没了。remark阶段值处理漏标的。