我正在尝试找到一种方法来列出运行时对象所引用的对象。我知道有一种方法可以使用oql查询jvm,但我想做的是从程序内部查询它。我可以使用任何API吗?
答案 0 :(得分:3)
您可以通过反思(java.lang.reflect
)来完成。
如何描述in this article。基本上,鉴于此类具有私有成员:
public class Secret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
使用Reflection,您可以访问其所有成员(包括私有成员),包括其值。因此,您查看其所有数据成员以查看它们所引用的内容(当然,如果它们也引用其他对象,则可以重复该过程)。以下是访问其成员的方法(此代码也显示了方法,如果您只是对数据感兴趣,则可能不需要这些方法,但我认为没有任何理由将其拉出来):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class secretClass = instance.getClass();
// Print all the method names & execution result
Method methods[] = secretClass.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = secretClass.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
我修复了原始代码中的错误并做了一些小改动,以便更明确Hacker
与Secret
无关(main
除外) )。
更新:关于基类中的字段,请回答下面的问题,这是更新的Hacker
,这样做(我假设您不想尝试枚举字段在Object
上,所以我已经停在那里了):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class cls = instance.getClass();
while (cls != null && cls != Object.class) {
System.out.println("From class: " + cls.getName());
// Print all the method names & execution result
Method methods[] = cls.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = cls.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
// Go to the base class
cls = cls.getSuperclass();
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
与
结合使用时public class BaseSecret {
private String baseSecretCode = "It's a base secret";
}
和
public class Secret extends BaseSecret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
你得到:
$ java Hacker From class: Secret Access all the methods Method Name: getSecretCode Return type: class java.lang.String It's a secret Access all the fields Field Name: secretCode It's a secret From class: BaseSecret Access all the methods Access all the fields Field Name: baseSecretCode It's a base secret
答案 1 :(得分:-1)
您可以使用Object类的getClass()方法来获取对象的运行时类。