收录(一)

https://www.cnblogs.com/QG-whz/p/9647614.html

从一次线上故障思考Java问题定位思路

for(int i = 1 ;i <= totalPage ;i++) {

死循环

top -p 12309 -H

-p用于指定进程,-H用于获取每个线程的信息,从top输出的内容,可以看到有四个线程占用了非常高的CPU

jstack -l 12309 > stack.log

到这里可以确定的是,死循环引发了Full GC,四个GC线程一直尝试着回收内存,这四个线程将CPU占满。

可以在机器上使用jmap命令来生成head dump文件。

jmap -dump:live,format=b,file=headInfo.hprof 12309

[导致fullgc]live这个参数表示我们需要抓取的是目前在生命周期内的内存对象,也就是说GC收不走的对象,在这种场景下,我们需要的就是这些内存的信息。[定位回收不了的对象]

 ============================ ============================

https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247484783&idx=2&sn=d22116d6e9562e15a240bded40383e22&chksm=96cd4523a1bacc35f7eacfcc3d3d4dcd13947d6d612d9299256dc50a47e2d868a4d302bc9fb0&mpshare=1&scene=1&srcid=1106kmea3JQ2rdWuYyK61iFS&key=2839d46a2ccd1adac7aa3a9a6970c1cc6735be3193586ce90637ba6853aa8e66daff3bffae10f71d27c5f83a5e1d06c589e0deabd215857f19bd0b3c56ee0fdd08e993e3ec3fdf2fee805bedfc8ec759&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=WkTrW9fz23LjFqzeh3GP9TDogP98DJkZiwfc%2BEMNGIg4KlsUSWFD%2B43qMoUBtM%2FM

又发生频繁FGC,这次是谁的锅?

CPU飙升——top -H -p 91782——jstack -l 91782——发现频繁FullGC,应用假死

jmap -dump:format=b,file=91782.bin 91782——MAT

如果是正常的JVM示例,Histogram试图最占内存的是byte[]和char[]两个数组,两者合计一般会占去80%左右的内存,远远超过其他对象占用的内存。

private static void buildBar(){
    List<FutureContract> futureContractList = getAllFutureContract();
    futureContractList.forEach(contract -> {
        // do something
        executor.scheduleWithFixedDelay(() -> {
            try{
                doFutureContract(contract);
            }catch (Exception e){
                e.printStackTrace();
            }
        }, 2, 3, TimeUnit.SECONDS);
    });
}

 ============================ ============================

https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247484902&idx=1&sn=96f8859450bb410702710a31207547b4&chksm=96cd45aaa1baccbca47d6e7f94c45d343e4700f970f08619892f212368c21a37b85cdacaf05e&mpshare=1&scene=1&srcid=11211UifsB4uzpR8997c8ijo&key=2558871502c06575459481704f05bca512ba4957d6fa81ce5b6e485d2f8c51d37700580aea5c270d91be776d01e698f3ee52c3eaa932f7093711cf0d03fef7c4b4b8c1cfe9ced87ba11c546b2b843cda&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=WkTrW9fz23LjFqzeh3GP9TDogP98DJkZiwfc%2BEMNGIg4KlsUSWFD%2B43qMoUBtM%2FM

OMG!又一个频繁FullGC的案例

这个案例比较特殊,虽然FGC频繁,但是每次FGC后,Old都能降下去。

-XX:+HeapDumpAfterFullGC和-XX:+HeapDumpBeforeFullGC。看命名就知道,这两个参数是在FGC前后生成dump文件。需要注意的是,一定是发生FGC,而不是CMS GC或者G1这种并发GC。

方法1-增大Young区——方法2-优化代码,循环体内确保没有大对象常驻

List<Long> userList = getUserIdByPage(pageNo);
List<UserAppMongo> userAppMongoList = new ArrayList<>(userList.size());
for (Long userId:userList){
    List<AppFromMySQL> appFromMySQLList = getUserInstalledAppList(userId);

假设每一页1000个用户,用户平均安装的APP数量为100个。那么处理每一页时总计有20w个对象一直常驻,且无法被GC掉

============================ ============================

https://mp.weixin.qq.com/s?__biz=MzIwMzY1OTU1NQ==&mid=2247485100&idx=1&sn=c98df81d8ce7518f56f2543c1b426c14&chksm=96cd46e0a1bacff61860cd4238adec40c36a154180ba3ea53adaf3a7bbdaf61928df56022890&mpshare=1&scene=1&srcid=1219XAIPdx3TS93oq00419h8&key=98f2add0c56609ce5c94c118687c26c283cde8e7d72bf35c01484a25db234e9fa1861166582b6731bdbb11e49a8151c6d4a821b99a63dc3402d00a5b16a09812be62b3e3bb61ed9bd8346c73d76845dd&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=WkTrW9fz23LjFqzeh3GP9TDogP98DJkZiwfc%2BEMNGIg4KlsUSWFD%2B43qMoUBtM%2FM

 一次 Java 内存泄漏排查过程,涨姿势

我们决定用一个单独的 executor 跑 CompetableFuture。但是,我们因此就需要等待所有的 CompetableFuture 都工作完……通过存储他们的引用,然后调用 join()。这导致一直到索引完成,所有的 future 的引用,以及它们引用到的数据,都保持着生存的状态。这阻止了垃圾收集器及时的把它们清理掉

大量的过早提升

如果一个对象的生命周期很短,但是它仍然晋升到了老年代,我们就把这种现象叫做过早提升(premature tenuring)(或者叫过早升级)。老年代里的对象通常都比较大,使用与新生代不同的 GC 算法,而这些过早提升的对象占据了老年代的空间,所以它们会影响 GC 的性能。因此,我们想竭力避免过早提升。

能想到的第一件事就是简单的增加新生代的空间。默认情况下,G1 的 GC 可以自动的调整新生代的空间,允许新生代使用堆内存的 5% 至 60%。我注意到运行的应用里,新生代和老年代的比例一直在一个很宽的幅度里变化,不过我依然动手修改了两个参数:-XX:G1NewSizePercent=40 和 -XX:G1MaxNewSizePercent=90看看会发生什么。

建议试试设置 -XX:G1MixedGCLiveThresholdPercent=100。这个设置应该会强制 G1 GC 在 mixed GC 时不去考虑它们被填充了多少,而是强制清理所有的老年代,因此也同时清理了从新生代过早提升的对象。这应该会阻止老年代被填满从而产生一次 full GC。

一个我们可以尝试的选项是转换到 CMS(Concurrent Mark Sweep)GC,不过由于它已经被废弃了,我们还是尽量不去使用它。

************************************************https://www.cnblogs.com/silyvin/p/10253766.html

====================================================================================

https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&mid=2247485836&idx=2&sn=fc470db16f01caaafe456993fb68a234&chksm=fa49763dcd3eff2b4793d925e62a492f3f4aeea133566c048200cb7cfc1efd05a0d8e12e2ac2&mpshare=1&scene=1&srcid=1215XdXRFyt9yHpUlat0Q2k6&key=2839d46a2ccd1ada2f83742edc46fa10e80ee51d5166317547ee53a9d27526a619a5c9bd1dc15057c7584f8a79f134f289163ce62047fbd7f0f14528d609d6aacc2fcf93f518f82923b35f12e98403a8&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=9rgp7yzXt5n8w9zh1MRq1i83%2BkhrOxABmxKneg1WadnOgS9TWM04YR%2BRF92XVaxK

涨姿势 | 服务重启后,为什么发生抖动?

top -H -p——jstack

"C2 CompilerThread1" daemon prio=10 tid=0x00007fce48125800 nid=0x852 waiting on condition [0x0000000000000000]``java.lang.Thread.State: RUNNABLE``Locked ownable synchronizers:``- None``"C2 CompilerThread0" daemon prio=10 tid=0x00007fce48123000 nid=0x851 waiting on condition [0x0000000000000000]``java.lang.Thread.State: RUNNABLE``Locked ownable synchronizers:``- None

C2 CompilerThread线程项目启动初期cpu使用率那么高,它在干什么呢?

Java程序在启动的时候所有代码的执行都处于解释执行模式,只有在运行了一段时间后,根据代码方法执行的次数,或代码里循环的执行次数等达到一定的阈值才会编译成机器码,编译成机器码后执行效率会得到大幅提升,而随着执行时间进一步拉长,JVM的各种更高级的编译优化手段就会逐渐加上,例如if条件的执行状况,逃逸分析等。这里的C2 CompilerThread线程干的就是编译优化的活。

 

解决:

1)通过tcpcopy软件拷贝一份线上nginx的流量进行预热,完成之后再导入线上流量。

2)可以使用-XX:CICompilerCount参数来设置编译线程数目,这个值默认是2(之前在栈里看到有两个编译线程),我们可以加到4。

3)

编译方式有三种:1)Client模式;2)Server模式;3)Tiered模式。我们服务默认是Server模式。

Server模式是采用c2高级编译的,会比较耗时且要运行一段时间才会触发编译。 Server模式的优点是编译后程序效率较高;

Client模式比较轻量也比较快触发(比Server模式触发快),编译优化后程序效率不如Server模式;

Tiered模式是Client模式和Server模式的折中,一开始会启用Client模式,可以在启动后更快的让部分代码先进入编译优化阶段,之后会启动Server模式,达到程序效率最大优化的目的。

Oracle JDK 7里的HotSpot VM已经开始有比较好的Tiered编译(tiered compilation)支持,可以设置参数-XX:+TieredCompilation来启动Tiered模式,java 8默认就是Tiered模式。

可以看出Tired模式开始阶段性能与C1相当,当到达某一时刻后性能与C2相当。

原文地址:https://www.cnblogs.com/silyvin/p/10226774.html