簡體   English   中英

如何在1類Java中加載同一Jar的2個版本

[英]How to load 2 versions of the same Jar in 1 class Java

這是一個復雜的問題,但我會盡力描述我的問題。

我需要在頂級類(v1.jar和v2.jar)中加載同一JAR的2個版本,這樣我就可以訪問這兩個版本的jar。 這是因為我想測試v2.jar中的任何功能是否已從v1.jar回歸

在我的頂級類中,我想調用v1.jar和v2.jar的方法,然后驗證v1對v2輸出的輸出。 這樣我就可以確定沒有搞砸了。

class Common {

    // Names of the classes would be the same so not sure how I would invoke the classes from the 2 different jars? 
   String resultv1 = EngineV1.run("a","b","c");
   String resultv2 = EngineV2.run("a","b","c");

   Assert.equals(resultv1, resultv2, "Regression has been introduced...");


}

我無法將v1和v2 jar作為maven依賴項導入,因為這會在maven中創建版本沖突,默認情況下maven將使用最新的jar。 所以我考慮創建一個通用接口,並具有該接口的2個不同的實現類。 然后在頂層我可以使用類加載器來加載v1和v2等等。但是這種方式不起作用,因為我必須更改生產v1.jar來實現公共接口。

任何幫助或見解將不勝感激。 如果可能的話,我非常希望看到樣品。 請不要將我介紹給其他主題

您的測試類可以為每個.jar文件設置ClassLoader 最簡單的方法是使用URLClassLoader

例:

File jar1 = new File("/path/to/v1.jar");
File jar2 = new File("/path/to/v2.jar");

URLClassLoader v1Loader = URLClassLoader.newInstance(new URL[] { jar1.toURI().toURL() });
URLClassLoader v2Loader = URLClassLoader.newInstance(new URL[] { jar2.toURI().toURL() });

Class<?> engineClass1 = v1Loader.loadClass("org.example.Engine");
Class<?> engineClass2 = v2Loader.loadClass("org.example.Engine");

Method runMethod1 = engineClass1.getMethod("run");
Method runMethod2 = engineClass2.getMethod("run");

Object engine1 = engineClass1.newInstance();
Object engine2 = engineClass2.newInstance();

String result1 = (String) runMethod1.invoke(engine1);
String result2 = (String) runMethod2.invoke(engine2);

請注意,由於.jar文件都不在測試代碼的類路徑中,因此代碼無法從.jar文件聲明任何類型的變量。 必須使用反射完成測試代碼的所有訪問。


UPDATE

您可能還需要在進行調用時更改上下文類加載器:

String result1, result2;
Thread thread = Thread.currentThread();
ClassLoader myLoader = thread.getContextClassLoader();
try {
    thread.setContextClassLoader(v1Loader);
    result1 = (String) runMethod1.invoke(engine1);
    thread.setContextClassLoader(v2Loader);
    result2 = (String) runMethod2.invoke(engine2);
} finally {
    thread.setContextClassLoader(myLoader);
}
// Compare result1 and result2

我從一個不同的Stackoverflow問題中發現了這個問題,我需要在運行時加載jar

    /*
    * Adds the supplied Java Archive library to java.class.path. This is benign
    * if the library is already loaded.
    */
   public static synchronized void loadLibrary(java.io.File jar) throws Exception {
       try {
           /*We are using reflection here to circumvent encapsulation; addURL is not public*/
           java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
           java.net.URL url = jar.toURI().toURL();

           /*Disallow if already loaded*/
           for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
               if (it.equals(url)){
                   return;
               }
           }
           java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
           method.setAccessible(true); /*promote the method to public access*/
           method.invoke(loader, new Object[]{url});
       } catch (final java.lang.NoSuchMethodException | 
           java.lang.IllegalAccessException | 
           java.net.MalformedURLException | 
           java.lang.reflect.InvocationTargetException e){
           throw new Exception(e);
       }
   }

適合我的目的

暫無
暫無

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

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