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

本文介绍了如何使用Java反射技术来遍历并打印Jar包内的所有类名和方法。当遇到ClassNotFoundException时,可能是因为类依赖了其他Jar包。解决方案包括将引用的Jar文件放在可找到的位置、创建包含所有依赖的Uber-jar,或者编写特殊类加载器。建议避免使用JAR-in-a-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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值