Question

Is there any way to retrieve the declaring class of an instance at runtime? For example:

public class Caller {
    private JFrame frame = new JFrame("Test");
    private JButton button = new JButton("Test me");
    private Callee callee = new Callee();

    public Caller() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(button);

        button.addActionListener(callee.getListener());

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        new Caller();
    }
}

The callee:

public class Callee {
    public ActionListener getListener() {
        return new ActionListener() {
        @Override
            public void actionPerformed(ActionEvent e) {
                /* Get the class "Caller" here and invoke its methods */
                /* Something along the lines of: */
                Object button = e.getSource();
                button.getOwnerClass(); //This would return the type Caller
            }
        };
    }
}

"getOwnerClass()" is an imaginary method. Is there a way to get a result similar to that?

Was it helpful?

Solution

There is nothing in the standard API that allows you to get this information. It's a bit unclear what you mean with 'declaring class' or 'owner class' but for this sake of this answer I'll assume that it is the class whose code created the instance of the object (that you want the owner class from).

This information is not stored by the JVM by default.

But, using the heap profiler that is packaged along with the JDK distribution, you can record the stacktrace of the point at which objects are allocated, and this information can be written to a file on various points in time.

That still doesn't give you an API call to retrieve the information, but it shows that it is technically possible to record this type of information.

I search a bit on Google and found that someone did create an API that uses the same basic technique as the heap profiler (the java.lang.instrumentation package/JVMTI interface)

With a bit of work you should be able to build something with it.

The site has a nice example:

AllocationRecorder.addSampler(new Sampler() {
    public void sampleAllocation(int count, String desc, Object newObj, long size) {
      System.out.println("I just allocated the object " + newObj + 
        " of type " + desc + " whose size is " + size);
      if (count != -1) { System.out.println("It's an array of size " + count); }
    }
});

Instead of printing, you should get the stacktrace using new Exception().getStackTrace(), remove the first few StackTraceElement objects that refer to the sampler and the API classes, and then call StackTraceElement.getClassName() to get the name of the class that created the object instance, in other words, your OwnerClass.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top