![](/img/trans.png)
[英]java list all methods and classes in a jar file of specific package using cmd
[英]How can I list all methods of all imported classes in a file using Java?
我的目标是查看外部文件的一些代码行,然后计算调用 class 的函数数。
例如,如果我有以下代码:
import java.io.BufferedReader;
import whatever.MyClass;
import java.util.ArrayList;
...
...
public void example(){
InputStreamReader isr = new InputStreamReader (whatever);
MyClass object = new MyClass();
someArrayList.add(whatever2)
someArrayList.add(whatever3)
}
本例中BufferedReader
和MyClass
函数被调用了一次, ArrayList
函数被调用了两次。
我的解决方案是获取所用类中所有方法的列表,并尝试与我的代码中的一些字符串匹配。 对于在我的项目中创建的类,我可以执行以下操作:
jar -tf jarPath
这会返回 JAR 中的类列表。并执行以下操作:
javap -cp jarPath className
我可以获得 JAR 内所有方法的列表,并带有特定的 class 名称。 但是,我该怎么做才能获得外部方法名称,例如“外部” class java.util.ArrayList
的add(...)
? 我无法访问 java.util.ArrayList 的.jar
文件, java.util.ArrayList
吗? 有人有其他建议来达到目标吗?
编译器不会将导入放入 object 文件中。 它把它们扔掉了。 Import 只是编译器的简写。(Imports 是一个编译时特性)。
第一步:
使用 Qdox https://github.com/paul-hammant/qdox获取 class 中的所有导入:
String fileFullPath = "Your\\java\\ file \\full\\path";
JavaDocBuilder builder = new JavaDocBuilder();
builder.addSource(new FileReader( fileFullPath ));
JavaSource src = builder.getSources()[0];
String[] imports = src.getImports();
for ( String imp : imports )
{
System.out.println(imp);
}
第二步:从该代码中获得灵感,循环导入(字符串数组)并应用相同的代码,您将获得这些方法。
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Tes {
public static void main(String[] args) {
Class c;
try {
c = Class.forName("java.util.ArrayList");
Arrays.stream(getAccessibleMethods(c)).
forEach(System.out::println);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Method[] getAccessibleMethods(Class clazz) {
List<Method> result = new ArrayList<Method>();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
result.add(method);
}
clazz = clazz.getSuperclass();
}
return result.toArray(new Method[result.size()]);
}
}
Output:
public void java.util.ArrayList.add(int,java.lang.Object)
public boolean java.util.ArrayList.add(java.lang.Object)
public boolean java.util.ArrayList.remove(java.lang.Object)
public java.lang.Object java.util.ArrayList.remove(int)
public java.lang.Object java.util.ArrayList.get(int)
public java.lang.Object java.util.ArrayList.clone()
public int java.util.ArrayList.indexOf(java.lang.Object)
public void java.util.ArrayList.clear()
.
.
.
所有代码 - 一个 class:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.thoughtworks.qdox.JavaDocBuilder;
import com.thoughtworks.qdox.model.JavaSource;
public class Tester {
public static void main(String[] args) {
// put your .java file path
// CyclicB is a class within another project in my pc
String fileFullPath =
"C:\\Users\\OUSSEMA\\Desktop\\dev\\OCP_Preparation\\src\\w\\CyclicB.java";
JavaDocBuilder builder = new JavaDocBuilder();
try {
builder.addSource(new FileReader( fileFullPath ));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JavaSource src = builder.getSources()[0];
String[] imports = src.getImports();
for ( String imp : imports )
{
Class c;
try {
c = Class.forName(imp);
Arrays.stream(getAccessibleMethods(c)).
forEach(System.out::println);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public static Method[] getAccessibleMethods(Class clazz) {
List<Method> result = new ArrayList<Method>();
while (clazz != null) {
for (Method method : clazz.getDeclaredMethods()) {
result.add(method);
}
clazz = clazz.getSuperclass();
}
return result.toArray(new Method[result.size()]);
}
}
Output 在文件 CyclicB.java 中导入的类中的所有方法:
private void java.lang.Throwable.printStackTrace(java.lang.Throwable$PrintStreamOrWriter)
public void java.lang.Throwable.printStackTrace(java.io.PrintStream)
public void java.lang.Throwable.printStackTrace()
public void java.lang.Throwable.printStackTrace(java.io.PrintWriter)
public synchronized java.lang.Throwable java.lang.Throwable.fillInStackTrace()
.
.
.
您可以查看具有 Java 编译器的OpenJDK项目。 学习构建修改后的版本。 调查此编译器的语法分析层并找到处理方法调用的位置。 将日志记录放入这些位置,现在您只需使用修改后的编译器构建 java 文件即可获取有关调用的信息。
构建很复杂,但您可能只需要仔细编辑几个文件。 这并不是很容易实现的目标,但我认为应该可以发现这些文件并对其进行更改,并且仍然可能是比实现自己的 Java 语法解析器(也可以使用JavaCC )更简单/更干净的方法。
如果您还需要跟踪来自外部库的调用,也可以使用修改后的编译器构建它们,您将获得所需的记录。
GNU Classpath是另一个开源项目,您可以在其中做类似的事情,而且构建起来可能更容易。 但是,与 OpenJDK 不同的是,GNU Classpath java 系统库并不完整。
这种方法可能不会发现一些在反射期间调用的方法。 但是它会发现调用了反射框架方法。 如果是安全相关的项目,最简单的就是同意不允许反射。 在不是框架的普通 Java 应用程序中使用反射是不常见的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.