attach java_JVM Attach机制实现

感谢支付宝同事【寒泉子】的投稿attach是什么在讲这个之前,我们先来点大家都知道的东西,当我们感觉线程一直卡在某个地方,想知道卡在哪里,首先想到的是进行线程dump,而常用的命令是jstack ,我们就可以看到如下线程栈了大家是否注意过上面圈起来的两个线程,”Attach Listener”和“Signal Dispatcher”,这两个线程是我们这次要讲的attach机制的关键,先偷偷告诉各位...
摘要由CSDN通过智能技术生成

感谢支付宝同事【寒泉子】的投稿

attach是什么

在讲这个之前,我们先来点大家都知道的东西,当我们感觉线程一直卡在某个地方,想知道卡在哪里,首先想到的是进行线程dump,而常用的命令是jstack ,我们就可以看到如下线程栈了

Snip20140314_179.png

大家是否注意过上面圈起来的两个线程,”Attach Listener”和“Signal Dispatcher”,这两个线程是我们这次要讲的attach机制的关键,先偷偷告诉各位,其实Attach Listener这个线程在jvm起来的时候可能并没有的,后面会细说。

那attach机制是什么?说简单点就是jvm提供一种jvm进程间通信的能力,能让一个进程传命令给另外一个进程,并让它执行内部的一些操作,比如说我们为了让另外一个jvm进程把线程dump出来,那么我们跑了一个jstack的进程,然后传了个pid的参数,告诉它要哪个进程进行线程dump,既然是两个进程,那肯定涉及到进程间通信,以及传输协议的定义,比如要执行什么操作,传了什么参数等。

attach能做些什么

总结起来说,比如内存dump,线程dump,类信息统计(比如加载的类及大小以及实例个数等),动态加载agent(使用过btrace的应该不陌生),动态设置vm flag(但是并不是所有的flag都可以设置的,因为有些flag是在jvm启动过程中使用的,是一次性的),打印vm flag,获取系统属性等,这些对应的源码(attachListener.cpp)如下

static AttachOperationFunctionInfo funcs[] = {

{ "agentProperties", get_agent_properties },

{ "datadump", data_dump },

{ "dumpheap", dump_heap },

{ "load", JvmtiExport::load_agent_library },

{ "properties", get_system_properties },

{ "threaddump", thread_dump },

{ "inspectheap", heap_inspection },

{ "setflag", set_flag },

{ "printflag", print_flag },

{ "jcmd", jcmd },

{ NULL, NULL }

};

后面是命令对应的处理函数。

attach在jvm里如何实现的

Attach Listener线程的创建

前面也提到了,jvm在启动过程中可能并没有启动Attach Listener这个线程,可以通过jvm参数来启动,代码(Threads::create_vm)如下:

if (!DisableAttachMechanism) {

if (StartAttachListener || AttachListener::init_at_startup()) {

AttachListener::init();

}

}

bool AttachListener::init_at_startup() {

if (ReduceSignalUsage) {

return true;

} else {

return false;

}

}

其中DisableAttachMechanism,StartAttachListener ,ReduceSignalUsage均默认是false(globals.hpp)

product(bool, DisableAttachMechanism, false, \

"Disable mechanism that allows tools to attach to this VM”)

product(bool, StartAttachListener, false, \

"Always start Attach Listener at VM startup")

product(bool, ReduceSignalUsage, false, \

"Reduce the use of OS signals in Java and/or the VM”)

因此AttachListener::init()并不会被执行,而Attach Listener线程正是在此方法里创建的

// Starts the Attach Listener thread

void AttachListener::init() {

EXCEPTION_MARK;

klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK);

instanceKlassHandle klass (THREAD, k);

instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);

const char thread_name[] = "Attach Listener";

Handle string = java_lang_String::create_from_str(thread_name, CHECK);

// Initialize thread_oop to put it into the system threadGroup

Handle thread_group (THREAD, Universe::system_thread_group());

JavaValue result(T_VOID);

JavaCalls::call_special(&result, thread_oop,

klass,

vmSymbols::object_initializer_name(),

vmSymbols::threadgroup_string_void_signature(),

thread_group,

string,

CHECK);

KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass());

JavaCalls::call_special(&result,

thread_group,

group,

vmSymbols::add_method_name(),

vmSymbols::thread_void_signature(),

thread_oop, // ARG 1

CHECK);

{ MutexLocker mu(Threads_lock);

JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry);

// Check that thread and osthread were created

if (listener_thread =&

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值