分享一个新出炉的JVM里不痛不痒的BUG(Attach机制相关)

本文来自: PerfMa技术社区

PerfMa(笨马网络)官网网络

概述

老早以前写过一篇文章,关于attach机制的,能够看下这篇老文章了解一下JVM源码分析之Attach机制实现彻底解读,好比你们经常使用的jstack,jmap等工具的主要原理都和attach机制有关,在JVM里处理这些命令的线程主要是Attach Listener这个线程,这个线程在JVM里是惟一的,我以前也一直觉得是惟一的,可是咱们同事最近在作一个线程分析产品的时候,发现咱们抓到了多个Attach Listener线程,这让我也很疑惑,我第一感受是不可能,确定是数据抓错了,直到亲眼看到了两个同名的Attach Listener线程我才不得不相信原来还真有这种状况。多线程

image.png

问题分析

不过从Attach Listener的实现来看,它设计的初衷不该该是一个多线程的设计,因而我昨晚上又翻了一遍代码,发现还真可能存在这种状况。举个栗子,当咱们不少人同时执行jstack的时候,就可能会发生,固然有个前提是以前都没有作过任何和attach相关的操做。异步

Attach Listener线程默认状况下不会在JVM启动的时候就建立,固然也有一个JVM参数能够指定在JVM启动的时候就启动这个线程,这个就不会存在咱们今天讨论的这个问题了,这个JVM参数是-XX:+StartAttachListener函数

当咱们在运行时触发attach机制的时候,首先会经过Signal Dispatcher线程来建立Attach Listener线程,代码以下:工具

image.png

image.png

在上面的圈起来的init方法里会建立Attach Listener线程,可是在init方法执行以前会经过_initialized属性来判断是否须要建立线程,而_initialized设置为true是在attach_listener_thread_entry里,这个是Attach Listener Thread的entry,也就是当这个线程执行的时候执行的方法。源码分析

image.png

可是在设置_initialized=true以前,若是有多个请求信号发出了(好比同时又不少jstack命令触发),可能会建立多个Attach Listener,由于Signal DispatcherAttach Listener线程是异步执行的。学习

问题复现

为了让效果更明显,咱们能够在hotspot里修改下代码从新编译下再跑demospa

image.png

在上面函数里加上圈起来的这段代码,表示在设置_initialized属性以前停留15s,当进程起来以后,不断执行jstack <pid>,最终将会看到有很是多的Attach Listener线程线程

image.png

其实问题的根本就是有一个空档期(设置_initialized为true以前)可能存在屡次建立线程的可能。设计

总结

总的来讲,建立Attach Listener线程是经过Signal Dispatcher线程来建立的,可是决定Signal Dispatcher是否能够重复建立Attach Listener线程的标记是在某个Attach Listener线程里设置的,若是没有及时设置该标记,就可能存在建立多个Attach Listener线程的状况。

一块儿来学习吧

PerfMa KO 系列课之 JVM 参数【Memory篇】

实战:一次疑似内存泄漏的问题排查

相关文章
相关标签/搜索