簡體   English   中英

當前運行的 class 或 JAR 文件的位置

[英]Location of currently running class or JAR file

我有一個Lotus Notes數據庫,它正在與遠程 web 服務進行一些交互。 我編寫了一個自定義 Java class 來執行交互。

class 方法可以從三個位置之一執行,具體取決於用戶的設置:

  1. 在通過 Lotus Notes Java 代理調用的 Java 腳本庫中
  2. 在位於用戶“jvm/lib/ext”目錄的 JAR 文件中
  3. 在 JAR 文件中,該文件位於用戶的“jvm/lib”目錄(例如,“jvm/lib/custom_dir”)內的自定義目錄中。 Lotus Notes JVM 通過使用“JavaUserClassesExt”本地 notes.ini 變量了解自定義目錄。

在我的 class 中,我只想能夠返回當前 class 正在執行的位置。 因此,如果它從選項 2 或選項 3 執行,則返回 JAR 文件路徑。 如果它從選項 1 執行,則返回我可以處理的其他內容。

我試過以下。

getProtectionDomain() 方法

getClass().getProtectionDomain().getCodeSource().getLocation()

結果是:

java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)

沒有選項可以更改運行此設置的任何客戶端上的任何安全設置。

Class.getResource 方法

String myName = "/" + getClass().getName().replace('.', '/') + ".class";
URL myResourceURL = getClass().getResource(myName);

結果: myResourceURL 始終為 null。

ClassLoader.getResource 方法

String myName2 = getClass().getName().replace('.', '/') + ".class";
ClassLoader myCL = getClass().getClassLoader();
URL myResourceURL2 = myCL.getResource(myName);

結果: myResourceURL2 始終為 null。

a)我在上面哪里出錯了?

b) 如何使用不同的方法獲取當前正在執行的 class 的位置?

我已經設法通過將我的代碼包裝在“AccessController.doPrivileged”塊中來克服這個問題,即:

final String[] myLocationViaProtectionDomain = {null};
AccessController.doPrivileged(new PrivilegedAction(){
    public Object run(){
        myLocationViaProtectionDomain[0] = getClass().getProtectionDomain().getCodeSource().getLocation().toString();
        debug("myLocationViaProtectionDomain: " + myLocationViaProtectionDomain[0]);
        return null;
    }
});

有趣的是,當 JAR 文件位於客戶端的 JVM 目錄(即我原來的帖子中的第 2 點和第 3 點)中時,這種方法完全符合我的要求。 但是,當從 Java 腳本庫中執行代碼時運行相同的代碼時,將引發以下異常:

java.security.AccessControlException: Access denied (java.lang.RuntimePermission getProtectionDomain)

這很好,因為至少在 1 和 (2 & 3) 之間存在差異,然后我可以正確處理。

來自 lekkimworld.com(Twitter:@lekkim)的優秀 Mikkel 向我指出了這個解決方案,非常感謝 go 給他。

我不確定這是否有幫助,但我們“切換”我們的user.dir (系統屬性)以確保我們為我們的應用程序“運行”某個目錄。 在我們的例子中,我們有一個 web 啟動應用程序,我們通過 Lotus Notes 啟動它(它調用一個 BAT 文件,它調用Java Web 啟動(JAWS)...)

但無論如何,我們要做的是以下。

//Normally you don't ever want to do this......
Class clazz = ClassLoader.class;
Field field = clazz.getDeclaredField("sys_paths");
field.setAccessible(true);
field.setClass(clazz, null);
try {
     //Basically we read in the path and then loop through and remove our current
     //directory which is where we tend to "kick off from" rather than where we want
     //to run from.
     String minusCurrentDir = removeCurrentDirectoryFromPath(System.getProperty("java.library.path");
     System.setProperty("java.library.path", minusCurrentDir);
}
finally {
     field.setAccessible(true);
}

現在稍后您可以訪問和修改user.dir屬性或詢問它在哪里。 這可能使您可以訪問所需的內容(?),或者至少頂級代碼可能會有所幫助。

您的最后一行代碼有myCL.getResouce(myName) ,它應該使用myName2代替。 這可能會導致問題。 如果它使用帶有前導“/”的名稱版本,那么您將不會從 ClassLoader.getResource() 調用中獲得任何信息。 它必須沒有前導斜杠。 如果這沒有幫助,您也可以嘗試:

ClassLoader.getSystemResource(myName2); // name without leading slash

如果這仍然不起作用,則可能是安全問題。 根據ClassLoader.getResource() 文檔,如果“調用者沒有足夠的權限來獲取資源”,它可以返回 null。 我只知道Java,不是Lotus,所以不知道它運行代碼的安全環境是什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM