精华内容
下载资源
问答
  • 首先我们要清楚,死循环会导致当前线程cpu一直处于使用中状态。所以我们首先要找到最近一段时间cpu使用100%的线程,然后找到它所运行的代码块。 使用到的工具:arthas、jmap、jvisualvm 找到最近cpu使用100%的线程...

    首先我们要清楚,死循环会导致当前线程cpu一直处于使用中状态。所以我们首先要找到最近一段时间cpu使用100%的线程,然后找到它所运行的代码块。
    使用到的工具:arthas、jmap、jvisualvm

    1. 找到最近cpu使用100%的线程
      在arthas环境下运行dashboard命令,该命令5秒统计一次,但是线程【pool-1-thread-1】cpu使用时间为4.859,几乎是100%,可以和其它线程比较非常突出,那就是它了
      在这里插入图片描述

    2. 导出dump文件
      先使用jps找到对应的进程编号【xxx】
      再使用命令导出 jmap -dump:format=b,file=/logs/heap.hprof xxx(进程编号)

    3. 打开jvisualvm分析dump文件找到代码块
      mac本运行jvisualvm命令直接打开jvm分析工具,或者运行命令echo $JAVA_HOME找到bin目录运行命令打开
      windows找到jdk安装bin目录打开jvisualvm.exe

    • 点击左上角,选择文件类型选择hprof,文件选择/tmp/dump001.hprof,点击打开
      在这里插入图片描述
    • 打开后点击【堆转储上的线程】的显示线程
      在这里插入图片描述
    • 找到线程【pool-1-thread-1】运行的代码行
      在这里插入图片描述
      end
      附件
      arthas安装教程见官网:https://arthas.gitee.io/install-detail.html
      代码块如下
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Random;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 死循环验证
     */
    @Slf4j
    public class DeadCircleTest {
        public static void main(String[] args) throws InterruptedException {
            ExecutorService executorService = Executors.newFixedThreadPool(4);
            Runnable run = () -> {
                List<TestOom> list = new LinkedList<>();
                int cnt = (int) (new Random().nextDouble() * 100);
                while (cnt > 0) {
                    list.add(new TestOom());
                    cnt --;
                }
                log.info("finish: {}", cnt);
            };
            executorService.submit(() -> {
                Thread.sleep(30000);
                long point = (System.currentTimeMillis() / 1000);
                while (true) {
                    long cu = System.currentTimeMillis() / 1000;
                    if (point != cu) {
                        log.info("print...");
                        point = cu;
                    }
                }
            });
            while (true) {
                try {
                    executorService.submit(run);
                    Thread.sleep(1000);
                } catch (Exception e) {
                    log.error("提交任务异常");
                }
            }
        }
    }
    
    展开全文
  • 定位java中的死循环

    2021-03-06 18:16:39
    kafka里还没有数据,原来是有死循环代码.如何定位呢?先top 找到占用CPU最大的进程top - 03:11:00 up 52 days, 17:50, 5 users, load average: 0.99, 0.97, 0.99Tasks: 149 total, 1 running, 148 sleeping, 0 s...

    kafaka consumer突然CPU占用100%..  kafka里还没有数据,原来是有死循环代码.

    如何定位呢?

    先top 找到占用CPU最大的进程

    top - 03:11:00 up 52 days, 17:50,  5 users,  load average: 0.99, 0.97, 0.99

    Tasks: 149 total,   1 running, 148 sleeping,   0 stopped,   0 zombie

    Cpu(s): 10.6%us, 15.1%sy,  0.0%ni, 74.3%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

    Mem:   3859888k total,  3362444k used,   497444k free,   186664k buffers

    Swap:   524280k total,   412704k used,   111576k free,   403636k cached

    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

    23485 root      20   0 2665m 425m  13m S  0.0 11.3  48:38.02 java

    28605 root      20   0 1654m 410m  16m S  0.0 10.9   0:17.55 java

    12862 root      20   0 2635m 393m 3516 S 100.6 10.4  21826:30 java

    20337 root      20   0 1681m 174m 5308 S  0.0  4.6  49:29.67 java

    19670 root      20   0 1630m 138m 4764 S  0.0  3.7  50:51.80 java

    0818b9ca8b590ca3270a3433284dd417.png

    然后查看这个进程下哪个线程占用的资源最多top -Hp 12862

    [root@tsbqacdhhbm1 ~]# top -Hp 12862

    top - 03:16:07 up 52 days, 17:55,  5 users,  load average: 0.99, 0.97, 0.99

    Tasks:  47 total,   1 running,  46 sleeping,   0 stopped,   0 zombie

    Cpu(s):  9.4%us, 16.3%sy,  0.0%ni, 74.2%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

    Mem:   3859888k total,  3356104k used,   503784k free,   187052k buffers

    Swap:   524280k total,   412620k used,   111660k free,   403724k cached

    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

    12907 root      20   0 2635m 393m 3576 R 100.2 10.4  21520:32 java

    13878 root      20   0 2635m 393m 3576 S  0.3 10.4  12:27.99 java

    12862 root      20   0 2635m 393m 3576 S  0.0 10.4   0:00.00 java

    12863 root      20   0 2635m 393m 3576 S  0.0 10.4   0:01.96 java

    0818b9ca8b590ca3270a3433284dd417.png

    定位到12907这个线程  把它转化成16进制是 326b

    用 jstack -l 12862 > jstack.log; 生成线程堆栈日志文件

    打开jstack.log文件  搜索0x326b

    0818b9ca8b590ca3270a3433284dd417.png

    0818b9ca8b590ca3270a3433284dd417.png

    "pool-3-thread-2" prio=10 tid=0x00007fb780235000 nid=0x326b runnable [0x00007fb7c89c2000]

    java.lang.Thread.State: RUNNABLE

    at com.elasticsearch.river.kafka.KafkaRiver$UpLoadFileWorker.run(KafkaRiver.java:303)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

    at java.lang.Thread.run(Thread.java:744)

    Locked ownable synchronizers:

    - <0x00000000f04077f8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

    定位到死循环的代码块,原因是没有sleep....

    展开全文
  • java2如何排查线上死循环发布时间:2020-11-06 17:51:55来源:亿速云阅读:111作者:Leah本篇文章给大家分享的是有关java2如何排查线上死循环,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以...

    java2如何排查线上死循环

    发布时间:2020-11-06 17:51:55

    来源:亿速云

    阅读:111

    作者:Leah

    本篇文章给大家分享的是有关java2如何排查线上死循环,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

    排查方法,因为是线上的linux,没有用jvm监控工具rim链接上去。

    只好用命令排查:

    top cpu排序,一个java进程cpu到500%了,什么鬼.....

    查到对应java进程

    jps || ps -aux | grep 端口pid=13455

    查看进程中线程使用情况 T排序 查看cpu占用time最高的线程编号top -Hp 13455

    有个线程9877 的时间一直在爆涨

    获取线程十六进制地址9877 (十六进制一定要小写)printf "%x\n" 9877

    执行 jstack 13455|grep -10 2695(线程十六进制号)

    如果想查看完整信息,可导出文本,查找jstack -l 9839 > jstack.log-9893

    "qtp750044075-25" #25 prio=5 os_prio=0 tid=0x00007f83354e5000 nid=0x2695 runnable [0x00007f830e5d8000]

    java.lang.Thread.State: RUNNABLE

    at java.text.DateFormatSymbols.(DateFormatSymbols.java:145)

    at sun.util.locale.provider.DateFormatSymbolsProviderImpl.getInstance(DateFormatSymbolsProviderImpl.java:85)

    at java.text.DateFormatSymbols.getProviderInstance(DateFormatSymbols.java:364)

    at java.text.DateFormatSymbols.getInstance(DateFormatSymbols.java:340)

    at java.util.Calendar.getDisplayName(Calendar.java:2110)

    at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1125)

    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:966)

    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)

    at java.text.DateFormat.format(DateFormat.java:345)

    at com.huiwan.gdata.modules.gdata.util.TimeUtil.getDay(TimeUtil.java:383)

    at com.huiwan.gdata.modules.gdata.publ.retain.service.impl.Retain3ServiceImpl.act(Retain3ServiceImpl.java:119)

    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

    at java.lang.reflect.Method.invoke(Method.java:498)

    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)

    .......略

    Locked ownable synchronizers:

    - None

    f017fd09dfba76a605a83750e8d3852d.png

    定住到Retain3ServiceImpl.java:119

    这行,马的,有人写了个while循环,用字符串时间比较,之前表是date类型,后改为datetime类型,多了00:00:00永远也没一样的时间,一直在那while.....还搞了个json对象默认加0......

    改了这里的代码,就好了,cpu就没上去了.

    补充知识:记一次线上Java程序导致服务器CPU占用率过高的问题排除过程

    1、故障现象

    客服同事反馈平台系统运行缓慢,网页卡顿严重,多次重启系统后问题依然存在,使用top命令查看服务器情况,发现CPU占用率过高。

    2、CPU占用过高问题定位

    2.1、定位问题进程

    使用top命令查看资源占用情况,发现pid为14063的进程占用了大量的CPU资源,CPU占用率高达776.1%,内存占用率也达到了29.8%

    [ylp@ylp-web-01 ~]$ top

    top - 14:51:10 up 233 days, 11:40, 7 users, load average: 6.85, 5.62, 3.97

    Tasks: 192 total, 2 running, 190 sleeping, 0 stopped, 0 zombie

    %Cpu(s): 97.3 us, 0.3 sy, 0.0 ni, 2.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st

    KiB Mem : 16268652 total, 5114392 free, 6907028 used, 4247232 buff/cache

    KiB Swap: 4063228 total, 3989708 free, 73520 used. 8751512 avail Mem

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

    14063 ylp 20 0 9260488 4.627g 11976 S 776.1 29.8 117:41.66 java

    2.2、定位问题线程

    使用ps -mp pid -o THREAD,tid,time命令查看该进程的线程情况,发现该进程的多个线程占用率很高

    [ylp@ylp-web-01 ~]$ ps -mp 14063 -o THREAD,tid,time

    USER %CPU PRI SCNT WCHAN USER SYSTEM TID TIME

    ylp 361 - - - - - - 02:05:58

    ylp 0.0 19 - futex_ - - 14063 00:00:00

    ylp 0.0 19 - poll_s - - 14064 00:00:00

    ylp 44.5 19 - - - - 14065 00:15:30

    ylp 44.5 19 - - - - 14066 00:15:30

    ylp 44.4 19 - - - - 14067 00:15:29

    ylp 44.5 19 - - - - 14068 00:15:30

    ylp 44.5 19 - - - - 14069 00:15:30

    ylp 44.5 19 - - - - 14070 00:15:30

    ylp 44.5 19 - - - - 14071 00:15:30

    ylp 44.6 19 - - - - 14072 00:15:32

    ylp 2.2 19 - futex_ - - 14073 00:00:46

    ylp 0.0 19 - futex_ - - 14074 00:00:00

    ylp 0.0 19 - futex_ - - 14075 00:00:00

    ylp 0.0 19 - futex_ - - 14076 00:00:00

    ylp 0.7 19 - futex_ - - 14077 00:00:15

    从输出信息可以看出,14065~14072之间的线程CPU占用率都很高

    2.3、查看问题线程堆栈

    挑选TID为14065的线程,查看该线程的堆栈情况,先将线程id转为16进制,使用printf "%x\n" tid命令进行转换[ylp@ylp-web-01 ~]$ printf "%x\n" 14065

    36f1

    再使用jstack命令打印线程堆栈信息,命令格式:jstack pid |grep tid -A 30

    [ylp@ylp-web-01 ~]$ jstack 14063 |grep 36f1 -A 30

    "GC task thread#0 (ParallelGC)" prio=10 tid=0x00007fa35001e800 nid=0x36f1 runnable

    "GC task thread#1 (ParallelGC)" prio=10 tid=0x00007fa350020800 nid=0x36f2 runnable

    "GC task thread#2 (ParallelGC)" prio=10 tid=0x00007fa350022800 nid=0x36f3 runnable

    "GC task thread#3 (ParallelGC)" prio=10 tid=0x00007fa350024000 nid=0x36f4 runnable

    "GC task thread#4 (ParallelGC)" prio=10 tid=0x00007fa350026000 nid=0x36f5 runnable

    "GC task thread#5 (ParallelGC)" prio=10 tid=0x00007fa350028000 nid=0x36f6 runnable

    "GC task thread#6 (ParallelGC)" prio=10 tid=0x00007fa350029800 nid=0x36f7 runnable

    "GC task thread#7 (ParallelGC)" prio=10 tid=0x00007fa35002b800 nid=0x36f8 runnable

    "VM Periodic Task Thread" prio=10 tid=0x00007fa3500a8800 nid=0x3700 waiting on condition

    JNI global references: 392

    从输出信息可以看出,此线程是JVM的gc线程。此时可以基本确定是内存不足或内存泄露导致gc线程持续运行,导致CPU占用过高。

    所以接下来我们要找的内存方面的问题

    3、内存问题定位

    3.1、使用jstat -gcutil命令查看进程的内存情况

    [ylp@ylp-web-01 ~]$ jstat -gcutil 14063 2000 10

    S0 S1 E O P YGC YGCT FGC FGCT GCT

    0.00 0.00 100.00 99.99 26.31 42 21.917 218 1484.830 1506.747

    0.00 0.00 100.00 99.99 26.31 42 21.917 218 1484.830 1506.747

    0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484

    0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484

    0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484

    0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484

    0.00 0.00 100.00 99.99 26.31 42 21.917 219 1496.567 1518.484

    0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355

    0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355

    0.00 0.00 100.00 99.99 26.31 42 21.917 220 1505.439 1527.355

    从输出信息可以看出,Eden区内存占用100%,Old区内存占用99.99%,Full GC的次数高达220次,并且频繁Full GC,Full GC的持续时间也特别长,平均每次Full GC耗时6.8秒(1505.439/220)。根据这些信息,基本可以确定是程序代码上出现了问题,可能存在不合理创建对象的地方

    3.2、分析堆栈

    使用jstack命令查看进程的堆栈情况[ylp@ylp-web-01 ~]$ jstack 14063 >>jstack.out

    把jstack.out文件从服务器拿到本地后,用编辑器查找带有项目目录并且线程状态是RUNABLE的相关信息,从图中可以看出ActivityUtil.java类的447行正在使用HashMap.put()方法

    ded32f6eb521e4e7b7a4ac7095a71c52.png

    3.3、代码定位

    打开项目工程,找到ActivityUtil类的477行,代码如下:

    5ff47c35a6c5fb2232c9dd5fcabbe456.png

    找到相关同事了解后,这段代码会从数据库中获取配置,并根据数据库中remain的值进行循环,在循环中会一直对HashMap进行put操作。

    查询数据库中的配置,发现remain的数量巨大

    c6f27dbce9ce842654908fe38b72cca6.png

    以上就是java2如何排查线上死循环,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

    展开全文
  • 什么是jstack jstack的主要作用是查看或者导出...死循环 当线程停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道线程的执行过程中在后台做了哪些事,在等待哪些资源造成的卡顿。 使用方法 命令格式 jstack

    什么是jstack

    • jstack的主要作用是查看或者导出java线程的堆栈信息(快照);用于堆栈跟踪,当我们使用jstack命令时,它会将指定进程内的所有线程中方法的调用栈打印出来。

    线程快照是java虚拟机内每一个线程正在执行的方法堆栈的集合,生成线程快照的主要目的是用于定位线程出现问题的位置;常见的问题有

    • 响应时间长
    • 线程死锁
    • 死循环

    当线程停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道线程的执行过程中在后台做了哪些事,在等待哪些资源造成的卡顿。

    使用方法

    命令格式

    jstack [options] <pid>
    

    options 参数说明

    jstack的option参数并不多,真正用到的也就三个,接下来我们一个个介绍一下

    • -F :当线程挂起(Suspended)时,使用jstack -l pid命令是不会打印堆栈信息的,使用-F则可以强制输出线程堆栈;但是会停止但
    • -l:打印的信息除了堆栈外,还会显示锁的附加信息;
    • -m :同时输出java和C/C++的堆栈信息;在java的系统类库里面,有很多方法都是native修饰的,这些native修饰的方法你在java层面是看不到源码的,因为这些方法都是C/C++实现的;

    状态说明

    在线程的堆栈中,需要特别留意以下几种状态:

    • Deadlock: 死锁(重点关注)
    • Waiting on condition: 等待资源(重点关注)
    • Waiting on monitor entry : 等待获取监视器(重点关注)
    • Blocked :阻塞(重点关注)
    • Runnable :执行中
    • Suspended : 暂停
    • Object.wait()TIME_WAITING :对象等待中
    • Parked : 停止

    no option 参数

    不带option参数的命令

    jstack 12771
    

    打印结果如下

    # ......忽略其他堆栈信息我们只关注main线程的堆栈
    "main" #1 prio=5 os_prio=31 tid=0x00007fee9101a000 nid=0x2903 runnable [0x00007000085aa000]
       java.lang.Thread.State: RUNNABLE
    	at java.io.FileInputStream.readBytes(Native Method)
    	at java.io.FileInputStream.read(FileInputStream.java:255)
    	at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
    	at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
    	- locked <0x000000076ab1ead0> (a java.io.BufferedInputStream)
    	at com.test.Test.main(Test.java:12)
    # .......忽略其他堆栈信息我们只关注main线程的堆栈
    

    第一行各个单词的解析,

    • "main":线程名称 。
    • prio:线程优先级
    • tid:指Java Thread id。
    • nid:指native线程的id。。
    • [0x00007000085aa000]:线程栈起始地址。

    -l 打印锁的附加信息

    这里我们使用2个窗口,分别使用以下2个命令来测试

    # 第一个窗口执行
    jstack -l 12771
    
    # 第二个窗口中执行
    jstack  12771
    

    通过2个窗口对比可以看到,加了-l的命令多打印了锁的信息;
    在这里插入图片描述

    导出堆栈文件

    一般情况下,如果程序出错了, 都不会直接在生产环境的服务器上找错误,这个时候就可以用到一个非常实用的功能,将堆栈快照导出来,然后copy到别的电脑上看,命令如下

    jstack -l 2289 > jstackDump.txt
    

    执行后,就可以看到文件已经导出来了
    在这里插入图片描述
    通过cat命令可以看到,里面的内容和我们在命令行输出的内容是一样的
    在这里插入图片描述

    实战一 、 找出cpu占用最高的线程(linux系统)

    首先我们准备好一个死循环的线程,在线程内定一个while的死循环,并且给这个线程起个名字为:yexindogn,阿里巴巴的开发规范里面有一个规定,就是每个线程必须起一个名字,起名字就是为了 以后程序出问题的时候好找错误;

        public static void main(String[] args) throws InterruptedException {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(true){
                        System.out.println(112);
                    }
                }
            },"yexindong").start();
            System.out.println("我执行了");
        }
    

    接着我们将此代码打成jar包扔到linux服务器上运行,直接输入 java -jar Test.jar 命令即可运行,运行后我们可以看到控制台一直在输出112这个字符,这就代表程序已经在运行了;
    在这里插入图片描述
    接着在看下CPU的运行情况,使用top命令查看cpu占用情况,排在第一位的是进程号为30328的进程,占用了6.6%的cpu; 这边我使用了2个命令行连到同一台服务器,一个窗口用来运行刚刚的jar包,另一个窗口用来查找错误;
    在这里插入图片描述

    找线程 - 第一种方式

    知道进程号了,接着就是找线程了,输入以下命令

    top -Hp 30328
    

    打印结果如下,这里有一点需要注意,在我们加上-Hp指令后,PID展示就是线程的id了,这时候我们看到占用CPU最高的线程id是30365
    在这里插入图片描述

    找线程 - 第二种方式

    还有另一种方式,就是使用ps命令来查找线程

    ps -mp 30328 -o THREAD,tid,time| sort -n -k1 -r
    

    通过这个命令我们可以看到这边占用最高的线程id也是30365 ;
    在这里插入图片描述

    以上的方式我们成功找到了占用cpu高的线程id是30365,但这个id是十进制的,在这里需要先转为16进制,输入命令

    printf "%x\n" 30365
    

    计算出对应的16进制为:769d
    在这里插入图片描述

    当然也可以用其他的计算工具,比如mac系统自带计算器就支持进制之间的转换
    在这里插入图片描述

    使用jstack分析堆栈快照

    1、快速查找 (推荐使用)

    在命令行输入以下命令,这种方法更加快速,推荐使用

    jstack 12771 | grep -A 20 '769d'
    

    其中,grep 命令是查找结果为769d的内容,-A 20 表示打印匹配所在行的后20行内容。直接帮我们定位到所在线程的堆栈,结果如下

    "yexindong" #8 prio=5 os_prio=0 tid=0x00007effd0182000 nid=0x769d runnable [0x00007effbea0f000]
       java.lang.Thread.State: RUNNABLE
            at java.io.FileOutputStream.writeBytes(Native Method)
            at java.io.FileOutputStream.write(FileOutputStream.java:326)
            at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
            at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
            - locked <0x00000000ecd6ea10> (a java.io.BufferedOutputStream)
            at java.io.PrintStream.write(PrintStream.java:482)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
            at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
            at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
            - locked <0x00000000ecd659c8> (a java.io.OutputStreamWriter)
            at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
            at java.io.PrintStream.newLine(PrintStream.java:546)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at java.io.PrintStream.println(PrintStream.java:737)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at com.test.Test$1.run(Test.java:13)
            at java.lang.Thread.run(Thread.java:748)
    
    2、常规方法

    当然也可以用下面的死办法,先打印出所有的堆栈快照;

    jstack 30328
    

    打印结果如下

    [root@VM_0_5_centos ~]# jstack 30328
    2021-07-14 23:40:34
    Full thread dump OpenJDK 64-Bit Server VM (25.232-b09 mixed mode):
    
    "Attach Listener" #10 daemon prio=9 os_prio=0 tid=0x00007effa4001000 nid=0x12f9 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "DestroyJavaVM" #9 prio=5 os_prio=0 tid=0x00007effd004b800 nid=0x7679 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "yexindong" #8 prio=5 os_prio=0 tid=0x00007effd0182000 nid=0x769d runnable [0x00007effbea0f000]
       java.lang.Thread.State: RUNNABLE
            at java.io.FileOutputStream.writeBytes(Native Method)
            at java.io.FileOutputStream.write(FileOutputStream.java:326)
            at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
            at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
            - locked <0x00000000ecd6ea10> (a java.io.BufferedOutputStream)
            at java.io.PrintStream.write(PrintStream.java:482)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
            at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
            at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
            - locked <0x00000000ecd659c8> (a java.io.OutputStreamWriter)
            at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
            at java.io.PrintStream.newLine(PrintStream.java:546)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at java.io.PrintStream.println(PrintStream.java:737)
            - locked <0x00000000ecd65a10> (a java.io.PrintStream)
            at com.test.Test$1.run(Test.java:13)
            at java.lang.Thread.run(Thread.java:748)
    
    "Service Thread" #7 daemon prio=9 os_prio=0 tid=0x00007effd013e800 nid=0x769b runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C1 CompilerThread1" #6 daemon prio=9 os_prio=0 tid=0x00007effd013b800 nid=0x769a waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread0" #5 daemon prio=9 os_prio=0 tid=0x00007effd012d000 nid=0x768b waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Signal Dispatcher" #4 daemon prio=9 os_prio=0 tid=0x00007effd012a800 nid=0x7689 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Finalizer" #3 daemon prio=8 os_prio=0 tid=0x00007effd0101000 nid=0x7683 in Object.wait() [0x00007effbf906000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000ecd66260> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
            - locked <0x00000000ecd66260> (a java.lang.ref.ReferenceQueue$Lock)
            at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
            at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
    
    "Reference Handler" #2 daemon prio=10 os_prio=0 tid=0x00007effd00fc000 nid=0x767f in Object.wait() [0x00007effbfa07000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x00000000ecd66418> (a java.lang.ref.Reference$Lock)
            at java.lang.Object.wait(Object.java:502)
            at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
            - locked <0x00000000ecd66418> (a java.lang.ref.Reference$Lock)
            at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    
    "VM Thread" os_prio=0 tid=0x00007effd00f2800 nid=0x767d runnable 
    
    "VM Periodic Task Thread" os_prio=0 tid=0x00007effd0141000 nid=0x769c waiting on condition 
    
    JNI global references: 5
    

    接着我用刚刚计算出来的16进制复制出来在这里搜索一下,经过查看就知道是我们刚刚起了名字为yexindong的线程出错了,出错的位置在Test.java的第13行代码
    在这里插入图片描述
    我们看看java代码,确实是第13行这里的死循环导致的
    在这里插入图片描述

    实战二、 找出cpu占用最高的线程(windows系统)

    首先打开任务管理器,因为默认windows的任务管理器是不显示进程pid的,所以我们需要设置一下,选择 查看选择列(S)...

    在这里插入图片描述
    选中PID进程表示符后点击确定按钮
    在这里插入图片描述

    查进程号pid

    然后我们就可以看到占用CPU最高的java进程PID为:976
    在这里插入图片描述

    查线程号TID

    因为windows不能直接查看java进程中的线程信息,所以我们需要借助一个工具,这个工具是微软自己开发的,叫做Process Explorer ,网上很多,需要的童鞋请自行百度,打开后找到pid为976的进程右击选择 → 属性
    在这里插入图片描述
    在弹出的窗口中找到线程这一栏,它的排序默认就是按照cpu占用的率倒序排列的,所以最上面的就是占用cpu最高的线程了,记住它的线程id:3548
    在这里插入图片描述

    线程id转16进制

    刚刚拿到的进程id是十进制的,但是我们导出的jstack信息里面,线程id是以16进制来展示的,所以我们要先将这个线程id为3548转为16进制的,使用windows自带的计算器即可,在快捷命令行输入calc
    在这里插入图片描述
    计算器打开后将其设置为程序员使用的计算器
    在这里插入图片描述
    接着输入线程id3548,在按一下16进制,就会自动进行转换,结果为ddc,记住这个16进制;
    在这里插入图片描述

    使用jstack导出堆栈并分析

    在命令行输入以下指令导出进程的堆栈快照信息

    jstack 976 > jstackInfo.txt
    

    在这里插入图片描述
    几秒钟后,快照导出了,静静地躺在文件夹里,等待着我们打开
    在这里插入图片描述
    用Notepad++打开导出的文件,搜索刚刚计算出来的16进制ddc,就可以定位到线程出错的位置了
    在这里插入图片描述

    在java层面打印堆栈

    有些童鞋可能会觉得用这个jstack命令麻烦了,那java在代码里面可不可以打印出堆栈呢?你别说,还真有,就是这个方法:Thread.getAllStackTraces();光说不练假把式,来个demo测试一下吧

        public static void main(String[] args) throws InterruptedException {
    		// 第一个线程,死循环
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
    
                    }
                }
            },"while").start();
    		// 延时一秒
            Thread.sleep(1000);
            // 第二个线程,用来打印堆栈
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
                    for (Map.Entry<Thread, StackTraceElement[]> threadEntry : allStackTraces.entrySet()) {
                        Thread key = threadEntry.getKey();
                        System.out.println(key);
                        StackTraceElement[] value = threadEntry.getValue();
                        for (StackTraceElement stackTraceElement : value) {
                            System.out.println("      "+stackTraceElement.toString());
                        }
                    }
                }
            },"stack-info").start();
        }
    

    执行后打印结果如下,由此可以看到,将当前进程的所有线程都打印出来了,但是这边只打印了简单的堆栈信息,对于开发人员来说,已经起到了监控作用;

    Thread[Reference Handler,10,system]
          java.lang.Object.wait(Native Method)
          java.lang.Object.wait(Object.java:502)
          java.lang.ref.Reference.tryHandlePending(Reference.java:191)
          java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    Thread[while,5,main]
          com.test.Test$1.run(Test.java:29)
          java.lang.Thread.run(Thread.java:748)
    Thread[Monitor Ctrl-Break,5,main]
          java.net.SocketInputStream.socketRead0(Native Method)
          java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
          java.net.SocketInputStream.read(SocketInputStream.java:171)
          java.net.SocketInputStream.read(SocketInputStream.java:141)
          sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
          sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
          sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
          java.io.InputStreamReader.read(InputStreamReader.java:184)
          java.io.BufferedReader.fill(BufferedReader.java:161)
          java.io.BufferedReader.readLine(BufferedReader.java:324)
          java.io.BufferedReader.readLine(BufferedReader.java:389)
          com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:61)
    Thread[Finalizer,8,system]
          java.lang.Object.wait(Native Method)
          java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
          java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
          java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
    Thread[stack-info,5,main]
          java.lang.Thread.dumpThreads(Native Method)
          java.lang.Thread.getAllStackTraces(Thread.java:1610)
          com.test.Test$2.run(Test.java:39)
          java.lang.Thread.run(Thread.java:748)
    Thread[Attach Listener,9,system]
    Thread[Signal Dispatcher,9,system]
    
    

    作为调优和找错的工具来说,可以说jstack是用的最多的一个工具了,但是由于局限性,现在已经慢慢被替换掉了;大家更倾向于使用阿里巴巴开发的工具arthas;感兴趣的童鞋可以了解下!

    展开全文
  • 当我们运行java程序时,发现程序不动,但又不知道是哪里出问题时,...死循环写个死循环的程序如下:packageconcurrency;public classTest {public static void main(String[] args) throwsInterruptedException {whi...
  • 如何定位死循环或高CPU使用率(linux)确定是CPU过高使用top观察是否存在CPU使用率过高现象找出线程对CPU使用率过高的进程的所有线程进行排序ps H -e -o pid,tid,pcpu,cmd --sort=pcpu |grep xxx得到如下结果,其中线程...
  • 如何定位死循环或高CPU使用率(linux) 确定是CPU过高 使用top观察是否存在CPU使用率过高现象找出线程 对CPU使用率过高的进程的所有线程进行排序ps H -e -o pid,tid,pcpu,cmd --sort=pcpu |grep xxx得到如下结果,其中...
  • GDB定位程序死循环

    2021-08-16 11:46:40
    方法主要是GDB调试,这里先简单介绍一些GDB调试的三种类型。 1、调试一个可执行文件; 2、调试一个coredump文件(gcore pid让正在运行的...定位CPU占用过高 1、pstack pid 查看某正在运行的进程的函数调用栈信息,这...
  • 3.代码中存在死循环或循环产生过多重复的对象实体;4.使用的第三方软件中的BUG;5.启动参数内存值设定的过小内存溢出的解决方案:第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)第二步,...
  • JAVA问题定位跟踪技术

    2021-02-12 21:30:04
    常用的JAVA调试技巧:线程堆栈解读性能瓶颈分析远程调试内存泄露检测常用工具集:proc工具集系统跟踪命令truss/straceCore文件管理coreadm进程状态监控prstat网络状态监控netstat磁盘监控iostatCPU和内存监控vmstat...
  • 只好用命令排查:top cpu排序,一个java进程cpu到500%了,什么鬼.....查到对应java进程jps || ps -aux | grep 端口pid=13455查看进程中线程使用情况 T排序 查看cpu占用time最高的线程编号top -Hp ...
  • 最近在学习jdk的动态代理, 自己写了一个Demo后, 发现程序陷入了递归, 通过分析源码后, 成功定位并解决了问题, 也加深了自己对动态代理的理解. 代码 书写动态代理的一般步骤 定义接口, 如下面代码的Task接口,确定...
  • 当我们运行java程序时,发现程序不动,但又不知道是哪里出问题时,...死循环写个死循环的程序如下: packageconcurrency;public classTest {public static void main(String[] args) throwsInterruptedException {wh...
  • JDK1.8HashMap会发生死循环吗?

    千次阅读 多人点赞 2021-05-31 17:54:31
    面试官:JDK1.8HashMap会发生死循环吗?
  • /** * JAVA里面如何使用一个线程死亡或结束. * @ * */ public class T { public static void main(String[] args) { // 启动线程 MyThread thread = new MyThre自打stop不推荐使用后,我们还有别的...
  • jps命令,查询正在运行的虚拟机java进程,一般显示信息就是,pid和进程名称: 或者输入tasklist,找到java.exe的PID,如下为4268: (2) jstack 使用jstack [pid] 输出当前进程的堆栈信息。主要有两种使用...
  • 《《java循环结构》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《java循环结构》PPT课件.ppt(34页珍藏版)》请在人人文库网上搜索。1、循环结构(一),第五章,分别写出运行结果,switch(day) case 1: System.out....
  • 疑难杂症死锁、死循环、数据结构异常(过大或者被破坏)、集中等待外部服务回应等现象。这些异常现象通常采用jstack工具可以获取到非常有用的线索。 了解异常现象分类之后,我们来具体讲讲故障定位的步骤。 五、...
  • 或者受限于业务产品,根本就没办法出现性能问题,包括笔者自己遇到的性能问题也不多,所以为了提前储备知识,当出现问题的时候不会手忙脚乱,我们本篇文章来模拟下常见的几个Java性能故障,来学习怎么去分析和定位。...
  • 这边使用arthas去排查由于死循环引起的cpu升高问题。 问题: 例如在报错的时候打印日志时日志不全或者是没有给出错误状态码,那正常想到的就是改代码加日志重新部署?但如果是线程池的问题或者是一些不易复现,重启...
  • 对table[1]中的链表来说,进入while循环,此时e=key(3),那么next=key(7),经过计算重新定位e=key(3)在新表中的位置,并把e=key(3)挂在newTable[3]的位置 这样循环下去,将table[1]中的链表循环完成后,于是...
  • 采用Java开发的大型应用系统越来越大,越来越复杂,很多系统集成在一起,整个系统看起来像个黑盒子。总述如何输出线程堆栈?如何解读线程堆栈?线程的解读锁的解读线程状态的解读什么是线程堆栈?线程堆栈也称线程...
  • 对table[1]中的链表来说,进入while循环,此时e=key(3),那么next=key(7),经过计算重新定位e=key(3)在新表中的位置,并把e=key(3)挂在newTable[3]的位置 这样循环下去,将table[1]中的链表循环完成后,于是...
  • 即 while (true) {} 好了定位到代码中的位置了,当然生产环境中肯定不会写一个死循环的,有可能在特殊场景下出现死循环,或执行一个方法特别慢,用这种方法很快就能找到代码位置。 死锁 接着访问 curl localhost:...
  • java定位系统性能问题

    2021-02-27 13:25:26
    分析工具和命令:工具:eclipse、...也可以使用jdk自带的安装包目录下的C:\Program Files\Java\jdk1.8.0_161\bin\jvisualvm.exe 的工具来自行分析定位问题,jvisualvm工具只在JDK 6,JDK 7和JDK 8版本有提供,之后的版...
  •   HashMap并发情况下的死循环问题在jdk 1.7及之前版本存在的,jdk 1.8 通过增加loHead和loTail进行了修复,虽然进行了修复,但是如果涉及到并发情况下,一般建议使用CurrentHashMap替代HashMap来确保不会出现线程...
  • 在优先恢复现网服务正常后,开始着手定位Full GC的问题。在现场只能够抓到四个GC线程占用了很高的CPU,无法抓到引发Full GC的线程。查看了服务故障期间的错误日志,发现更多的是由于Full GC引起的问题服务异常日志,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,342
精华内容 12,936
关键字:

java死循环定位

java 订阅