![](/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.