1. 程式人生 > >利用反射打印出 Jar包中所有的類名和方法

利用反射打印出 Jar包中所有的類名和方法

public class Test {

public static void getJarClassNameAndMethod(String jarFile) throws Exception {
        try {
        File f=new File(jarFile);// 通過將給定路徑名字串轉換為抽象路徑名來建立一個新 File 例項
        URL url1=f.toURI().toURL();
            URLClassLoader myClassLoader=new URLClassLoader(new URL[]{url1},Thread.currentThread().getContextClassLoader()); 
            
               //通過jarFile 和JarEntry得到所有的類
              JarFile jar = new JarFile(jarFile);
              Enumeration<JarEntry> enumFiles = jar.entries();//返回 zip 檔案條目的列舉
              JarEntry entry; 
              while (enumFiles.hasMoreElements()) {//測試此列舉是否包含更多的元素。 
              entry = (JarEntry) enumFiles.nextElement();
                if (entry.getName().indexOf("META-INF") < 0) {
                    String classFullName = entry.getName();
                    if (classFullName.indexOf(".class") < 0)
                    {
                        classFullName = classFullName.substring(0, classFullName.length() - 1);
                    }
                    else
                    {

                        String className = classFullName.substring(0,classFullName.length()-6).replace("/", ".");//去掉字尾 .class
                        Class<?> myClass = myClassLoader.loadClass(className);
                        //通過getMethods得到類中包含的方法
                        Method m[] = myClass.getMethods();
                        System.out.println(className);    //列印類名                    
                        for(int i=0; i<m.length; i++)
                        {
                        String sm = m[i].getName();
                        if(DEFAULT_METHOD.indexOf(sm)<0){   //列印除預設方法外的方法
                        System.out.println(m[i].toString().substring((m[i].toString().indexOf(className))));
                        }

                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
private static String DEFAULT_METHOD= "waitequalsnotifynotifyAlltoStringhashCodegetClass"; //這些預設方法不用列印

public static void main(String[] args) throws Exception {
getJarClassNameAndMethod("F:\\test\\flowClient1.3.jar");//Jar包所在路徑
}

}

//如果出現ClassNotFoundException 說明你所反射的Jar包中 存在類依賴其他Jar包類載入過程的一部分,你要載入的類依賴於任何類也將被載入.

There are three solutions:

  • Put the referenced Jar file somewhere that it can be found (and set the manifest property accordingly.

  • Create an Uber-jar that combines the classes in your main JAR and all of the relevant library JARs into one JAR file.

  • Write a funky class loader that knows how to load from a JAR-in-a-JAR, and modify the application to instantiate and use the classloader. (This approach is NOT recommended ...)

Note that the first two alternatives solve the problem by getting rid of your JAR-in-a-JAR structure ... in different ways.

Supposed we have a jar called Main.jar for the application. This application needs Second.jar and Third.jar . In the manifest file of the first jar (Main.jar), you adjust the Class-Path setting :

Manifest-Version: 1.0
Main-Class: MyClass
Class-Path: Second.jar Third.jar
The value of the Class-Path attribute specifies the relative URLs of the extensions or libraries that this application or extension needs. URLs are separated by one or more spaces. The application or extension class loader uses the value of this attribute to construct its internal search path.