2009-04-28 19 views
6

Tôi muốn bằng cách nào đó đăng nhập mỗi lần Thread.interrupt() được gọi, ghi nhật ký mà Chủ đề đã phát hành cuộc gọi (và ngăn xếp hiện tại của nó) cũng như xác định thông tin về Chủ đề nào đang bị gián đoạn.Có cách nào trong Java để đăng nhập * mỗi * Thread ngắt?

Có cách nào để thực hiện việc này không? Tìm kiếm thông tin, tôi thấy ai đó tham chiếu đến khả năng triển khai trình quản lý bảo mật. Đây có phải là một cái gì đó có thể được thực hiện trong thời gian chạy (ví dụ, trong một máy khách Applet hoặc Web Start), hoặc bạn có cần phải công cụ JVM đã cài đặt để làm điều này không?

Hoặc có cách nào tốt hơn để thực hiện việc này không?

+0

Tôi có thể nghĩ ra một số cách để làm điều đó với độ phức tạp khác nhau và số lần truy cập hiệu suất khác nhau. Nó là một điều một lần để tìm một lỗi hoặc là nó một cái gì đó bạn muốn trong sản xuất? – Fredrik

+0

Đây chủ yếu là điều tôi muốn làm một lần, nhưng điều mà tôi biết tôi thỉnh thoảng muốn sử dụng. Nếu nó là đủ thân thiện, tôi sẽ để nó trong mã sản xuất nhưng bị vô hiệu hóa như là một chế độ bổ sung của gỡ lỗi từ xa (thông qua các bản ghi) được sử dụng khi cần thiết. – Eddie

Trả lời

9

Là một hack nhanh chóng, đây là dễ dàng hơn rất nhiều để làm hơn tôi nghĩ nó sẽ là. Do đây là một cách nhanh chóng hack, tôi không làm những việc như đảm bảo rằng các vết đống là đủ sâu trước dereferencing mảng, vv Tôi chèn như sau trong ký constructor của tôi Applet của:

log.info("Old security manager = " + System.getSecurityManager()); 
System.setSecurityManager(new SecurityManager() { 
     @Override 
     public void checkAccess(final Thread t) { 
     StackTraceElement[] list = Thread.currentThread().getStackTrace(); 
     StackTraceElement element = list[3]; 
     if (element.getMethodName().equals("interrupt")) { 
      log.info("CheckAccess to interrupt(Thread = " + t.getName() + ") - " 
        + element.getMethodName()); 
      dumpThreadStack(Thread.currentThread()); 
     } 
     super.checkAccess(t); 
     } 
    }); 

dumpThreadStack phương pháp là như sau:

public static void dumpThreadStack(final Thread thread) { 
    StringBuilder builder = new StringBuilder('\n'); 
    try { 
    for (StackTraceElement element : thread.getStackTrace()) { 
     builder.append(element.toString()).append('\n'); 
    } 
    } catch (SecurityException e) { /* ignore */ } 
    log.info(builder.toString()); 
} 

tôi có thể không bao giờ, tất nhiên, để lại điều này trong mã sản xuất, nhưng nó đủ để cho tôi biết chính xác chủ đề đã gây ra một interrupt() mà tôi không mong đợi. Đó là, với mã này tại chỗ, tôi nhận được một bãi chứa stack cho mỗi cuộc gọi đến Thread.interrupt().

+1

Lưu ý rằng trong một số phiên bản của java, SecurityManager cũng nên ghi đè lên phương thức checkPermission (cho tùy chọn dễ chấp nhận và đơn giản nhất), nếu chúng đơn giản trở về) hoặc bạn có thể gặp lỗi bảo mật như 'java.security.AccessControlException: access denied'. – vazor

4

Trước khi thử bất kỳ điều gì quá hoang dã, bạn có cân nhắc sử dụng Java debuggingAPI không? Tôi nghĩ rằng việc capture MethodEntryEvents trên Thread.interrupt() sẽ làm điều đó.

Eeek, đó là giao diện cũ, bạn cũng nên kiểm tra oout mới JVM ToolInterface.

+0

Tôi mơ hồ nhận biết được API gỡ lỗi Java, nhưng tôi không chắc chắn cách sử dụng nó từ bên trong ứng dụng mà tôi sẽ sử dụng nó. – Eddie

+0

Tôi đã cung cấp cho bạn một vài liên kết ngay bây giờ; câu trả lời ngắn gọn là bạn thêm một lá cờ vào lời gọi JVM, và sau đó có thể kết nối với JVM bên ngoài. –

+0

Thật không may, đề xuất của bạn sẽ không giúp tôi. Giao diện Công cụ JVM mới yêu cầu JNI và API gỡ lỗi Java cũ không có sẵn cho các Applets. Tuy nhiên, thông tin này có thể hữu ích cho những thứ khác trong tương lai. Cảm ơn các con trỏ. – Eddie

2

Tôi sẽ xem AspectJ và khả năng của nó để bao bọc các cuộc gọi phương thức. An execution pointcut xung quanh phương thức interrupt() sẽ trợ giúp tại đây.

Lưu ý rằng vì bạn đang tìm cách chặn cuộc gọi phương thức hệ thống Java (trái ngược với mã ứng dụng của bạn), trên có thể không phù hợp. This thread dường như đề xuất có thể, nhưng lưu ý rằng anh ta đã tạo một dệt rt.jar.

+0

Bạn thậm chí có thể bọc các phương thức trong các thư viện JVM? – Eddie

+0

Đó là một điểm tốt, và tôi đã xem xét ngay khi tôi gõ nó. Có nhiều cơ chế byte khác nhau, chắc chắn (thời gian biên dịch/thời gian chạy/tải lớp) vì vậy một trong số chúng có thể hoạt động. –

0

Bạn có thể thử cũng với JMX:

ManagementFactory.getThreadMXBean().getThreadInfo(aThreadID) 

với đối tượng ThreadInfo bạn có thể đăng:

  • stack trace của thread
  • thông tin userful chung chung như tên, trạng thái, vv
  • vv
.210

EDIT

getAllThreadIds sử dụng() để có được danh sách các id chủ đề live:

long[] ids = ManagementFactory.getThreadMXBean().getAllThreadIds(); 
+0

Làm thế nào để bạn có nghĩa là sẽ bắt các cuộc gọi gián đoạn? – Fredrik

+0

sử dụng phương pháp khác (công cụ JVM, móc gỡ lỗi, AOP, v.v ...)? – dfa

1

Như những người khác đã nói ... Nếu nó là một điều một lần JVMTI có lẽ là cách Hardcore nhất để đi. Tuy nhiên, cũng thú vị là sử dụng thư viện asm và các API thiết bị để tạo một tác nhân chèn một lời gọi tới một phương thức tĩnh mà bạn đã tạo trước cuộc gọi Thread.interrupt() (hoặc có thể làm thay đổi Thread.interrupt () để làm điều tương tự, tôi nghĩ bạn có thể làm điều đó).

Cả hai đều mất chút thời gian để tìm hiểu nhưng rất thú vị khi làm việc cùng và khi bạn nắm giữ nó, bạn có thể sử dụng chúng cho tất cả các loại điều thú vị trong tương lai :-) Tôi thực sự không có tốt đoạn để dán ở đây ngay bây giờ nhưng nếu bạn google xung quanh cho ASM và có thể nhìn vào JIP cho một số sử dụng sáng tạo của ASM tôi nghĩ rằng bạn sẽ tìm thấy cảm hứng.

JIP: Java Interactive Profiler

+0

Tôi cho rằng bạn đang đề cập đến http://asm.ow2.org/? Âm thanh rất sáng tạo! Tôi không có thời gian để điều tra, nhưng điều này trông giống như một cái gì đó sẽ làm tôi tốt trong tương lai. Cảm ơn. – Eddie

+0

Đúng, xin lỗi vì không bao gồm URL. – Fredrik

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