2017-02-27 47 views
0

我想要检索外部java .jar文件中的方法列表。这个外部jar不会被包含在我的构建路径中,我需要完全通过在代码中引用它来获取信息。用例是搜索已加载到我工作的应用程序中的.jar中的弃用方法。从外部Java获取方法.jar文件

我发现了几个在线解决方案并应用它们,但它们都期望某种东西或者是原生的,或者是构建路径。我将只能提供一个文件/文件路径作为参数,并基于此推导所有内容。

我的代码现在是如下,我正在寻找解决方案,以便如何使用我需要的方式。任何帮助将不胜感激!

public static void main(String[] args) throws IOException { 

    Collection<Class<?>> classes = new ArrayList<Class<?>>(); 

    JarFile jar = new JarFile("C:\\app\\folder\\jar\\file.jar"); 

    for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements();) 
    { 
     JarEntry entry = entries.nextElement(); 
     String file = entry.getName(); 

     if (file.endsWith(".class")) 
     { 

      String classname = file.replace('/','.').substring(0, file.length()-6); 
     System.out.println(classname); 

      try { 
       Class<?> c = Class.forName(classname); 
       classes.add(c); 
      } catch (Throwable e) { 
       System.out.println("WARNING: failed to instantiate " + classname + " from " + file); 
      } 
     } 
    } 
    for (Class<?> c: classes) 
     System.out.println(c); 
} 
+0

首先,您需要弄清楚您是否想使用由JVM加载的_classes_或数组中的_bytecode_。这些方法大不相同。 –

+0

你正在寻找'java.util.ServiceLoader'吗? – EJP

回答

1

您可以构建一个URLClassLoader与外部jar文件,并使用它来加载归类您在罐子里发现的。如果您有班级对象,则可以拨打getMethods()getDeclaredMethods()以获得班级的私人,受保护和公共方法。

public static void main(String[] args) throws Exception { 
     Set<Class<?>> classes = new HashSet<>(); 

     URL jarUrl = new URL("file:///C:/app/folder/jar/file.jar"); 
     URLClassLoader loader = new URLClassLoader(new URL[]{jarUrl}); 
     JarFile jar = new JarFile("C:\\app\\folder\\jar\\file.jar"); 

     for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements();) 
     { 
      JarEntry entry = entries.nextElement(); 
      String file = entry.getName(); 

      if (file.endsWith(".class")) 
      { 

       String classname = 
         file.replace('/', '.').substring(0, file.length() - 6).split("\\$")[0]; 
//    System.out.println(classname); 

       try { 
        Class<?> c = loader.loadClass(classname); 
        classes.add(c); 
       } catch (Throwable e) { 
        System.out.println("WARNING: failed to instantiate " + classname + " from " + file); 
       } 
      } 
     } 
     Map<String, List<Method>> collected = 
       classes.stream().collect(Collectors.toMap(Class::getName, clz -> { 
        List<Method> methods = new ArrayList<>(Arrays.asList(clz.getDeclaredMethods())); 
        methods.addAll(Arrays.asList(clz.getMethods())); 
        return methods; 
       })); 

     collected.forEach((clz, methods) -> System.out.println("\n" + clz + "\n\n" + methods)); 
    }