자바 도구 (jmap, jstack) 가 Liux 에서 의 소스 코드 분석 (2) 신호 처리
thread. cpp 에 서 는 주로 두 개의 스 레 드 를 만들어 신호 와 관련 된 것 을 처리 합 니 다.
JvmtiExport::enter_live_phase();
// Signal Dispatcher needs to be started before VMInit event is posted
os::signal_init();
// Start Attach Listener if +StartAttachListener or it can't be started lazily
if (!DisableAttachMechanism) {
if (StartAttachListener || AttachListener::init_at_startup()) {
AttachListener::init();
}
}
1. 신호 디 스 패 처 스 레 드
os. cpp 에서 의 signalinit () 함수 에서 signal dispatcher 스 레 드 를 시 작 했 습 니 다. signal dispatcher 스 레 드 는 주로 신 호 를 처리 하고 신 호 를 기다 리 며 배포 처 리 를 합 니 다. signal 을 자세히 볼 수 있 습 니 다.thread_entry 방법
static void signal_thread_entry(JavaThread* thread, TRAPS) {
os::set_priority(thread, NearMaxPriority);
while (true) {
int sig;
{
// FIXME : Currently we have not decieded what should be the status
// for this java thread blocked here. Once we decide about
// that we should fix this.
sig = os::signal_wait();
}
if (sig == os::sigexitnum_pd()) {
// Terminate the signal thread
return;
}
switch (sig) {
case SIGBREAK: {
// Check if the signal is a trigger to start the Attach Listener - in that
// case don't print stack traces.
if (!DisableAttachMechanism && AttachListener::is_init_trigger()) {
continue;
}
// Print stack traces
// Any SIGBREAK operations added here should make sure to flush
// the output stream (e.g. tty->flush()) after output. See 4803766.
// Each module also prints an extra carriage return after its output.
VM_PrintThreads op;
VMThread::execute(&op);
VM_PrintJNI jni_op;
VMThread::execute(&jni_op);
VM_FindDeadlocks op1(tty);
VMThread::execute(&op1);
Universe::print_heap_at_SIGBREAK();
if (PrintClassHistogram) {
VM_GC_HeapInspection op1(gclog_or_tty, true /* force full GC before heap inspection */,
true /* need_prologue */);
VMThread::execute(&op1);
}
if (JvmtiExport::should_post_data_dump()) {
JvmtiExport::post_data_dump();
}
break;
}
default: {
// Dispatch the signal to java
HandleMark hm(THREAD);
klassOop k = SystemDictionary::resolve_or_null(vmSymbolHandles::sun_misc_Signal(), THREAD);
KlassHandle klass (THREAD, k);
if (klass.not_null()) {
JavaValue result(T_VOID);
JavaCallArguments args;
args.push_int(sig);
JavaCalls::call_static(
&result,
klass,
vmSymbolHandles::dispatch_name(),
vmSymbolHandles::int_void_signature(),
&args,
THREAD
);
}
if (HAS_PENDING_EXCEPTION) {
// tty is initialized early so we don't expect it to be null, but
// if it is we can't risk doing an initialization that might
// trigger additional out-of-memory conditions
if (tty != NULL) {
char klass_name[256];
char tmp_sig_name[16];
const char* sig_name = "UNKNOWN";
instanceKlass::cast(PENDING_EXCEPTION->klass())->
name()->as_klass_external_name(klass_name, 256);
if (os::exception_name(sig, tmp_sig_name, 16) != NULL)
sig_name = tmp_sig_name;
warning("Exception %s occurred dispatching signal %s to handler"
"- the VM may need to be forcibly terminated",
klass_name, sig_name );
}
CLEAR_PENDING_EXCEPTION;
}
}
}
}
}
os::signalwait();신 호 를 기다 리 고 있 습 니 다. Liux 에 서 는 sem 을 통 해wait () 를 통 해 이 루어 집 니 다. SIGBREAK (Liux 의 QUIT) 신 호 를 받 았 을 때 (신호 처리 에 관 해 서 는 필자 의 다른 블 로그: 자바 에서 신호 처리 가 Liux 에서 이 루어 집 니 다) 를 참고 하 십시오. 처음으로 AttachListener::is 호출 을 통 해init_trigger () attach listener 스 레 드 를 초기 화 합 니 다. 2. Attach Listener 스 레 드 를 참조 하 십시오.
4. 567917. 첫 번 째 신 호 를 받 으 면 초기 화 를 시작 합 니 다. 초기 화 에 성공 하면 바로 돌아 갑 니 다. 또한 스 레 드 stack 의 정 보 를 되 돌려 주지 않 습 니 다 (socket file 을 통 해 되 돌아 갑 니 다). 그리고 두 번 째 는 초기 화 할 필요 가 없습니다.초기 화 에 성공 하지 못 하면 콘 솔 의 outputstream 에서 스 레 드 스 택 정 보 를 직접 인쇄 합 니 다
4. 567917. 두 번 째 신 호 를 받 았 습 니 다. 초기 화 되면 콘 솔 에서 스 레 드 스 택 정 보 를 직접 인쇄 합 니 다.초기 화 되 지 않 으 면 초기 화 를 계속 하고 처음 과 같은 절 차 를 밟 습 니 다
2. 수신 기 스 레 드 첨부
Attach Listener 스 레 드 는 외부 명령 을 받 고 이 명령 을 실행 하 며 결 과 를 발송 자 에 게 되 돌려 줍 니 다.jvm 가 시 작 될 때 + StartAttachListener 가 지정 되 지 않 으 면 이 스 레 드 는 시작 되 지 않 습 니 다. 방금 quit 신 호 를 받 은 후에 AttachListener::is 를 호출 하 는 것 에 대해 논 의 했 습 니 다.init_trigger () 호출 용 AttachListener::init () 를 통 해 Attach Listener 스 레 드 를 시작 하 는 동시에 서로 다른 운영 체제 에서 초기 화 되 었 습 니 다. Liux 에 서 는 attachListener 입 니 다.Linux. cpp 파일 에서 이 루어 졌 습 니 다.
linux 에서 파일 을 발견 하면. attachpid\# pid 가 존재 해 야 attach listener 스 레 드 를 시작 하고 socket 파일 을 초기 화 합 니 다. 즉, 보통 jmap, jstack tool 이 하 는 일 은 attach 를 먼저 만 듭 니 다.pid\# pid 파일 을 보 내 고 quit 신 호 를 보 냅 니 다. 이런 방식 으로 Attach Listener 스 레 드 를 몰래 시 작 했 습 니 다. (블 로그 참조:http://blog.csdn.net/raintungli/article/details/7023092).
스 레 드 구현 은 attachlistener_thread_entry 방법 체 에서 실현
static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {
os::set_priority(thread, NearMaxPriority);
if (AttachListener::pd_init() != 0) {
return;
}
AttachListener::set_initialized();
for (;;) {
AttachOperation* op = AttachListener::dequeue();
if (op == NULL) {
return; // dequeue failed or shutdown
}
ResourceMark rm;
bufferedStream st;
jint res = JNI_OK;
// handle special detachall operation
if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) {
AttachListener::detachall();
} else {
// find the function to dispatch too
AttachOperationFunctionInfo* info = NULL;
for (int i=0; funcs[i].name != NULL; i++) {
const char* name = funcs[i].name;
assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max");
if (strcmp(op->name(), name) == 0) {
info = &(funcs[i]);
break;
}
}
// check for platform dependent attach operation
if (info == NULL) {
info = AttachListener::pd_find_operation(op->name());
}
if (info != NULL) {
// dispatch to the function that implements this operation
res = (info->func)(op, &st);
} else {
st.print("Operation %s not recognized!", op->name());
res = JNI_ERR;
}
}
// operation complete - send result and output to client
op->complete(res, &st);
}
}
Attach Listener::dequeue ();liunx 에서 의 실현 은 방금 만 든 socket 파일 을 감청 하 는 것 입 니 다. 요청 이 들 어 오 면 요청 에 대응 하 는 동작 을 찾 고 호출 작업 이 결 과 를 얻어 이 socket 파일 에 결 과 를 기록 합 니 다. socket 파일 을 삭제 하면 jstack/jmap 에 오류 정보 unable to open socket file:.....
우 리 는 자주 사용한다. kill - 3 pid 의 작업 은 라인 스 택 정 보 를 인쇄 합 니 다. 구체 적 인 실현 은 Signal Dispatcher 스 레 드 에서 이 루어 진 것 을 볼 수 있 습 니 다. kill - 3 pid 는. attach 를 만 들 지 않 기 때 문 입 니 다.pid\# pid 파일 이 초기 화 되 지 않 아 스 레 드 의 스 택 정보 가 콘 솔 에 인쇄 되 었 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.