2014-11-07 13 views
8

Có nhiều cách để tạo các bãi chứa chuỗi trong java.Có cách nào để tạo ra một chuỗi java định kỳ sử dụng JVMTI không?

Tôi muốn sử dụng JVMTI (API C) để tạo nó, để đánh giá tác động hiệu suất của nó trên JVM đang chạy. (Tôi biết về jstack và JMX; câu hỏi này không phải là nói chung về việc nhận các bãi luồng, mà về việc sử dụng API JVMTI).

Tôi đang đặt mã của mình ở số this blog post. Trong đó, tác nhân java gắn vào tín hiệu SIGQUIT. Tôi muốn tránh điều đó, bởi vì đó là tín hiệu tương tự mà JVM sử dụng để viết một chuỗi kết xuất tới stdout. Tôi muốn tránh sự trùng lặp đó.

Nói cách khác, tôi muốn đính kèm với một tín hiệu khác hoặc tìm cách để tác nhân tạo ra một chuỗi kết xuất định kỳ.

+0

Không ai trong số các sự kiện trong jvmtiEventCallbacks trông phù hợp (trừ khi bạn muốn sử dụng DataDumpRequestion, nhưng nếu bạn đã làm, bạn sẽ không bị yêu cầu ở đây :)). Có vẻ như bạn tốt nhất nên nhờ đại lý của bạn gọi trực tiếp 'GetStackTrace'. Có lý do nào bạn không thể làm điều đó? –

+0

@ Paul-Hicks, Bạn có thể đăng một liên kết hoặc mã về cách tôi sẽ đính kèm vào jvm trong trường hợp này? – Ovesh

+0

Bạn đặt dll đại lý hoặc .so trong đường dẫn của jvm -agentpath hoặc xác định nó như là một -agentlib. Hãy xem [câu trả lời này] (http://stackoverflow.com/a/173447/3195526) hoặc [trang giới thiệu của IBM] (http://publib.boulder.ibm.com/infocenter/realtime/v2r0/index. jsp? topic =% 2Fcom.ibm.rt.doc.20% 2Fdiag% 2Ftools% 2Fjvmti.html). Đây có phải là điều bạn muốn biết không? Tôi có nên biến câu trả lời này thành câu trả lời không? –

Trả lời

2

Trong đó, tác nhân java gắn với tín hiệu SIGQUIT. Tôi muốn tránh điều đó, bởi vì đó là tín hiệu tương tự mà JVM sử dụng để viết một chuỗi kết xuất tới stdout. Tôi muốn tránh sự trùng lặp đó.

Chỉ cần xoá đoạn sau đây từ mã của bạn

/* Set callbacks and enable event notifications */ 
memset(&callbacks, 0, sizeof(callbacks)); 
callbacks.DataDumpRequest = &dumpThreadInfo; 
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); 
CHECK_JVMTI_ERROR(jvmti, err); 
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,JVMTI_EVENT_DATA_DUMP_REQUEST, NULL); 
CHECK_JVMTI_ERROR(jvmti, err); 

Tôi muốn thể đính kèm vào một tín hiệu khác nhau

Here is giấy, đó là một chút cũ, nhưng thông tin vẫn có liên quan.

Chỉ cần một mẫu như thế nào để làm một tín hiệu xử lý

import sun.misc.Signal; 
import sun.misc.SignalHandler; 

public class ThreadDumpSignalHandler implements SignalHandler { 
    private volatile SignalHandler old; 
    private ThreadDumpSignalHandler() { 

    } 
    public static void register(String sigName) { 
     ThreadDumpSignalHandler h = new ThreadDumpSignalHandler(); 
     h.old = Signal.handle(new Signal(sigName), h) 
    } 
    public void handle(Signal sig) { 
     threadDump(); 

     if(old != null && old != SIG_DFL && old != SIG_IGN) { 
      old.handle(sig); 
     } 
    } 
    // call your own threadDump native method. 
    // note that in the implementation of this method you are able to access jvmtiEnv from *gdata (see below) 
    private native void threadDump(); 
} 

ThreadDumpSignalHandler.register("INT"); 

Trong số nguyên nhân bạn có thể viết xử lý tín hiệu hoàn toàn tự nhiên (xin lưu ý rằng tôi đã không kiểm tra nó, đây chỉ là một ý kiến ​​cho rằng nên làm việc)

static sighandler_t old_handler; 
static void thread_dump_handler(int signum) { 
    if(gdata && gdata->jvmti) { 
     ... get thread dump 
    } 

    if(old_handler) { 
     old_handler(signum); 
    } 
} 

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { 
    old_handler = signal(SIGINT, thread_dump_handler); 

    ... 
} 

hoặc tìm cách cho các đại lý để tạo ra một bãi chứa thread theo định kỳ.

Trong mẫu của bạn có toàn cầu * gdata

typedef struct { 
    /* JVMTI Environment */ 
    jvmtiEnv  *jvmti; 
    jboolean  vm_is_started; 
    /* Data access Lock */ 
    jrawMonitorID lock; 
} GlobalAgentData; 

static GlobalAgentData *gdata; 

... do đó, chỉ cần có được jvmtiEnv từ đó bất cứ lúc nào bạn muốn (callbacks timer, vv)

+0

Nhận '* jvmti' từ' * gdata' an toàn? Tôi không chắc lắm về điều đó, nhưng tôi có thể thử. – Ovesh

+1

Nên an toàn. Ít nhất bạn luôn có thể sử dụng [RawMonitorEnter] (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#RawMonitorEnter) và [RawMonitorExit] (https://docs.oracle.com) /javase/7/docs/platform/jvmti/jvmti.html#RawMonitorExit) với gdata-> lock, nhưng tôi không nghĩ nó thực sự cần thiết cho đến khi bạn truy cập gdata-> jvmti đồng thời. – szhem

+1

Ngoài ra, bạn có thể tạo một luồng bằng [RunAgentThread] (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#RunAgentThread). [Start function] của thread (https://docs.oracle.com/javase/7/docs/platform/jvmti/jvmti.html#jvmtiStartFunction) chấp nhận jvmtiEnv làm tham số đầu tiên của nó. Vì vậy, bạn có thể thực hiện các chuỗi luồng định kỳ từ bên trong luồng được tạo ra nguyên gốc này. – szhem

-2

Không của các sự kiện trong jvmtiEventCallbacks trông phù hợp (trừ khi bạn muốn sử dụng DataDumpRequestion, nhưng nếu bạn đã làm, bạn sẽ không được hỏi ở đây: ok, do đó, đó là khá nhiều cách tôi đã đính kèm vào jvm cho đến nay (với sự khác biệt nhỏ). Vì vậy, tôi đoán điều đó đưa tôi đến câu hỏi tiếp theo: Làm thế nào để tôi có được một po liên quan đến một jvmtiEnv, để gọi GetStackTrace, nếu không phải từ một cuộc gọi lại? Vấn đề là để gọi t

2

Nếu mục tiêu của bạn là để định kỳ thu thập chủ đề bãi, bạn có thể sử dụng Java Flight Recorder, đó là một phần của Java Mission Controller

Bắt đầu với việc phát hành của Oracle JDK 7 Update 40 (7u40), Java Mission Control được đóng gói cùng với HotSpot JVM.

0

Các entry blog bạn trích dẫn có hầu hết những gì bạn cần cho JVMTI hệ thống ống nước. Bạn có thể sử dụng JVMTIenv từ gdata. Điều đó là hợp pháp. Hãy chắc chắn rằng nếu bạn đang thực hiện các cuộc gọi JNI để có một JNIenv thích hợp cho chuỗi hiện tại của bạn.

Bây giờ bạn cần phải thêm một cách để thông báo cho hành động của bạn (ví dụ: chủ đề dump). Xoay lên một sợi mà nghe trên một ổ cắm, sử dụng inotify, được đặt tên semaphores, vv .. - một cái gì đó mà bạn có thể poke từ bên ngoài.

Sau đó bạn có thể gọi dumpThreadInfo() từ xử lý sự kiện vòng lặp của bạn như bạn thấy phù hợp.

Các vấn đề liên quan