如何找到对象所指的内容?

发布于 2024-12-19 18:16:21 字数 86 浏览 2 评论 0原文

我正在尝试找到一种方法来列出运行时对象所引用的对象。我知道有一种方法可以使用 oql 查询 jvm,但我想做的是从程序内部查询它。有我可以使用的 API 吗?

I'm trying to find a way to list which objects a run-time object is referring to. I know there is a way to enquire the jvm using oql but what I'd like to do is to query it from inside a program. Is there any API I could use?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紧拥背影 2024-12-26 18:16:21

您可以通过反射来完成此操作(java.lang.reflect)。

本文如何描述。基本上,给定此类具有私有成员:

public class Secret {

    private String secretCode = "It's a secret";

    private String getSecretCode(){
        return secretCode;     
    }
}

通过反射,您可以访问其所有成员(包括私有成员),包括它们的值。因此,您查看其所有数据成员以了解它们引用的内容(当然,如果它们还引用其他对象,您可以重复该过程)。以下是如何访问他们的成员(此代码也显示了方法,如果您只对数据感兴趣,您可能不需要这些方法,但我没有看到任何充分的理由将该部分拉出来):

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();
        }
    }
}

我已经修复他们的原始代码中存在一个错误,并进行了一些小更改,以更清楚地表明 HackerSecret 没有任何关系(除了 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

You can do it via Reflection (java.lang.reflect).

How is described in this article. Basically, given this class that has private members:

public class Secret {

    private String secretCode = "It's a secret";

    private String getSecretCode(){
        return secretCode;     
    }
}

With Reflection, you can access all of its members (including the private ones), including their values. And so you look at all of its data members to see what they refer to (and of course, you can repeat the process if they also refer to other objects). Here's how to access their members (this code shows methods as well, which you probably won't need if you're just interested in data, but I didn't see any good reason to pull that part out):

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();
        }
    }
}

I've fixed a bug in their original code and made a small change to make it more clear that Hacker is not in any way tied to Secret (other than in main).

Update: Re your question below about the fields from base classes, here's an updated Hacker that does that (I've assumed you don't want to try to enumerate the fields on Object, so I've stopped there):

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();
        }
    }
}

When combined with

public class BaseSecret {

  private String baseSecretCode = "It's a base secret";

}

and

public class Secret extends BaseSecret {

    private String secretCode = "It's a secret";

    private String getSecretCode(){
        return secretCode;     
    }
}

you get:

$ 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
生死何惧 2024-12-26 18:16:21

您可以使用Object类的getClass()方法来获取对象的运行时类。

You can use getClass() method of Object class to get the runtime class of an object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文