2008-09-03 22 views
51

Có cách nào để tìm tên chương trình đang chạy trong Java không? Lớp học của phương pháp chính sẽ là đủ tốt.

Trả lời

45

Hãy thử điều này:

StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
    StackTraceElement main = stack[stack.length - 1]; 
    String mainClass = main.getClassName(); 

Tất nhiên, đây chỉ hoạt động nếu bạn đang chạy từ các chủ đề chính. Thật không may tôi không nghĩ rằng có một tài sản hệ thống bạn có thể truy vấn để tìm ra điều này.

Edit: kéo trong bình luận @ John Meagher, mà là một ý tưởng tuyệt vời:

Mở rộng trên @jodonnell bạn cũng có thể nhận được tất cả dấu vết ngăn xếp trong hệ thống sử dụng Thread.getAllStackTraces() . Từ , bạn có thể tìm kiếm tất cả các ngăn xếp dấu vết cho chuỗi "chính" để xác định lớp chính là gì. Điều này sẽ hoạt động ngay cả khi lớp học của bạn không phải là đang chạy trong chuỗi chính.

+0

Tốt lừa. Nói chung, người ta sẽ gọi nó từ main(), do đó, chỉ có một thread tại thời điểm này, nhưng trong trường hợp này được gọi từ nơi khác, chúng tôi tốt hơn có vấn đề này trong tâm trí ... – PhiLho

+4

Không có garantee chính thead để đang chạy khi bạn cố gắng tìm tên ứng dụng từ các chủ đề khác. Chủ đề chính có thể hoàn thành bình thường và một số chủ đề nền khác chưa hoàn thành. Đừng nghĩ rằng nó là hợp pháp để làm điều này lừa khác sau đó từ chủ đề chính. –

3

Cũng từ dòng lệnh, bạn có thể chạy công cụ jps. Âm thanh như một số điện thoại

jps -l 

sẽ giúp bạn có được những gì bạn muốn.

15

Để mở rộng trên @jodonnell, bạn cũng có thể nhận tất cả dấu vết ngăn xếp trong hệ thống bằng cách sử dụng Thread.getAllStackTraces(). Từ đó bạn có thể tìm kiếm tất cả các dấu vết ngăn xếp cho Chủ đề main để xác định lớp chính là gì. Điều này sẽ làm việc ngay cả khi lớp của bạn không chạy trong chuỗi chính.

+7

Có thể cho chủ đề chính ngừng chạy nhưng ứng dụng vẫn tiếp tục (các chuỗi không phải daemon khác). Điều này có thể xảy ra trong nhiều ứng dụng GUI/Swing vì thành ngữ phổ biến là cho chuỗi chính để gọi trên EDT để tạo khung đầu tiên và sau đó chấm dứt. –

-5

Hoặc bạn chỉ có thể sử dụng getClass(). Bạn có thể làm một cái gì đó như:

public class Foo 
{ 
    public static final String PROGNAME = new Foo().getClass().getName(); 
} 

Và sau đó progname sẽ có mặt bất cứ nơi nào bên trong Foo. Nếu bạn đang không ở trong một bối cảnh tĩnh, nó được dễ dàng hơn khi bạn có thể sử dụng này:

String myProgramName = this.getClass().getName(); 
+0

Tôi không nghĩ rằng điều này giải quyết được vấn đề. Các poster không biết lớp nào chứa phương thức 'main' được gọi khi Java khởi động (có lẽ nó là một phần của thư viện của bên thứ ba). –

+1

Điều này không có ý nghĩa gì cả. Nó chỉ hoạt động nếu tôi biết rằng 'Foo' là lớp chính. Nhưng sau đó tôi sẽ không cần phải làm điều này. – maaartinus

-3

Hãy thử điều này:

lớp

Java có trường hợp tĩnh của lớp riêng (java.lang.Class loại) của họ .

Điều đó có nghĩa là nếu chúng tôi có một lớp có tên là Chính. Sau đó chúng ta có thể nhận được dụ lớp của mình bằng Main.class

Nếu bạn quan tâm đến tên chỉ sau đó,

Chuỗi className = Main.class.getName();

+0

Nhưng trong trường hợp này bạn không biết lớp nào là lớp "chính". – ryantm

2

Đối với quyền truy cập vào các đối tượng lớp khi bạn đang ở trong một bối cảnh tĩnh

public final class ClassUtils { 
    public static final Class[] getClassContext() { 
     return new SecurityManager() { 
      protected Class[] getClassContext(){return super.getClassContext();} 
     }.getClassContext(); 
    }; 
    private ClassUtils() {}; 
    public static final Class getMyClass() { return getClassContext()[2];} 
    public static final Class getCallingClass() { return getClassContext()[3];} 
    public static final Class getMainClass() { 
     Class[] c = getClassContext(); 
     return c[c.length-1]; 
    } 
    public static final void main(final String[] arg) { 
     System.out.println(getMyClass()); 
     System.out.println(getCallingClass()); 
     System.out.println(getMainClass()); 
    } 
} 

Rõ ràng ở đây tất cả 3 cuộc gọi sẽ trở lại

class ClassUtils 

nhưng bạn có được hình ảnh;

classcontext[0] is the securitymanager 
classcontext[1] is the anonymous securitymanager 
classcontext[2] is the class with this funky getclasscontext method 
classcontext[3] is the calling class 
classcontext[last entry] is the root class of this thread. 
8

Đây là mã tôi đưa ra khi sử dụng phản hồi kết hợp của jodonnell và John Meagher. Nó lưu trữ các lớp học chính trong một biến tĩnh để giảm chi phí của các cuộc gọi lặp đi lặp lại:

private static Class<?> mainClass; 

public static Class<?> getMainClass() { 
    if (mainClass != null) 
    return mainClass; 

    Collection<StackTraceElement[]> stacks = Thread.getAllStackTraces().values(); 
    for (StackTraceElement[] currStack : stacks) { 
    if (currStack.length==0) 
     continue; 
    StackTraceElement lastElem = currStack[currStack.length - 1]; 
    if (lastElem.getMethodName().equals("main")) { 
     try { 
     String mainClassName = lastElem.getClassName(); 
     mainClass = Class.forName(mainClassName); 
     return mainClass; 
     } catch (ClassNotFoundException e) { 
     // bad class name in line containing main?! 
     // shouldn't happen 
     e.printStackTrace(); 
     } 
    } 
    } 
    return null; 
} 
16
System.getProperty("sun.java.command") 
+0

Xác minh trên JDK 1.7.0_07 – sourcedelica

+1

tôi tin rằng điều này chỉ hoạt động trên máy ảo HotSpot. xem http://java.dzone.com/articles/programmatically-restart-java – ericsoco

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