3

Is there a way to find no. of alive objects of a class at any point of time in a running application? By alive/live objects, I mean those objects which are NOT eligible for garbage collection. Is there any way to find it without using any tools?

Assume that the entire application is personally coded. So the classes can be customised as per our need. Also, assume that the class whose live instance count we want to find, is a user defined class, not any inbuilt class.

shanti
  • 270
  • 1
  • 4
  • 20
  • Without using any tools? No. – Louis Wasserman Dec 26 '15 at 18:06
  • http://stackoverflow.com/questions/2262620/how-to-find-the-number-of-objects-in-the-heap – sasi Dec 26 '15 at 18:07
  • 1
    If you need to know, you've got some architectural problem. Why do you think you need to know? – bmargulies Dec 26 '15 at 18:43
  • @bmargulies Just because it was an interview question. And even after a few days of searching, I couldn't find any suitable answer. Being an interview question also means that it could be answered in several ways. But I think what the interviewer wanted was to have a way explained, in which the application could be coded to achieve the objective (without using any extra tools). – shanti Dec 26 '15 at 18:46

2 Answers2

5

The simple answer is no - there is no simple class or method call to make to find this data. However, there are many ways that people have come up with. It depends on why you need the data and the structure of your program. There are good discussions on this topic here: http://www.coderanch.com/t/581790/java/java/ways-find-number-alive-instances and here: How to find the number of objects in the heap. Give some of those a try and see which works best for you.

Community
  • 1
  • 1
MrMadsen
  • 2,713
  • 3
  • 22
  • 31
-1

Yes.

Create a class based static instance counter that is synchronous

Up it by one in the class method(s) that instantiate..

Then u will have to override the dispose method to decrement instance counter..

UPDATE

Here is a nebulous class.. that can be used to track some things...

package myclasses;

import java.util.Vector;

public class ClassA {

    private static int iCountInstances = 0;
    private static int iCountCleanups = 0;
    private static int iCountGCFinalize = 0;

    private String m_str1 = null;
    private Vector m_vct1 = null;


    public ClassA() {
        // bump the instance count
        incrementCountInstance();


    }

    private static synchronized void incrementCountInstance() {
        iCountInstances++;
    }

    private static synchronized void incrementCountCleanup() {
        iCountCleanups++;
    }

    private static synchronized void incrementGCFinalize() {
        iCountGCFinalize++;
    }

    /**
     * reportOut - you can change this up on how ever you like
     * 
     * an in control app in a perfect world will have all three counts THE SAME after a final 
     * GC and right before exist.
     * 
     * The True number of 'active' classes in an app is going to be
     *      ICountInstances - iCountGCFinalize.
     * 
     * The idea here is that if GC did not dispose of it.. its still in memory.. and still 
     * active.. even if your app thinks its no longer using it...
     * 
     * @return
     */
    public static String reportOut() {

        return "ClassA Counts: incnt:" + ClassA.iCountInstances +", clncnt:" + ClassA.iCountCleanups + ", gccnt:" + ClassA.iCountGCFinalize;
    }


    public void cleanup() {

        //
        // ok.. initialize all member variables here
        // do not worry about what other object refereneces this guy
        // you only care about what you have as member variables.
        // you only de-refrence what you point to .. 
        // if every class took care of what it referenced.. then all is well.
        // so.. clean up your object and help GC ...

        this.setM_str1(null);
        this.getM_vct1().removeAllElements();

        ClassA.incrementCountCleanup(); // Increment the cleanup count..

        //
        // feel free to write to a logger reporting out that programmer has cleaned up this instance..
        //

    }

    @Override
    protected void finalize() throws Throwable
    {
        // Incrementing means GC determined this guy is truly an Object Orphan and has been 
        // completely de-referenced.

         ClassA.incrementGCFinalize();

        //
        // feel free to write to a logger reporting out that GC is removing this instance..
        //


    }
    public String getM_str1() {
        return m_str1;
    }

    public void setM_str1(String m_str1) {
        this.m_str1 = m_str1;
    }


    public void setM_vct1(Vector m_vct1) {
        this.m_vct1 = m_vct1;
    }

    public Vector getM_vct1() {
        return m_vct1;
    }
}

Here is another class that can be made to help report out whats going on during execution.. etc..

package myclasses;

public final class CheckCounts {


    // No create instance allowed..
    private CheckCounts() {

    }

    /**
     * Report out on interesting counts...
     */
    public static void reportOut() {

        /// Add all the reportouts here..
        System.out.println(ClassA.reportOut());


    }

}

You can get fancy with this and create a background thread monitor that simply reports out stats on the classes you want to track.. and have it write to a logger every 30 seconds or so..

Notice I count up everything. You can use math to see how effective your code is at cleaning up after itself.. When you clean up an object.. you want to dereference what that objected pointed to and clear out any lists, arrays, hashmaps, etc. Be careful though, dont go crazy, and start cleaning up objects that live in a Vector of your class - just clean up the vector itself...

Give it a try.. its easy to implement.. and it may help you see whats going on in a runtime env vs what you think is happening just by looking at your code..

DaveTheRave
  • 463
  • 2
  • 5
  • @DaveTheRave: override dispose method of which class? – shanti Dec 26 '15 at 18:23
  • @VinceEmigh Using finalize method doesn't seem logical because that method runs only at the time of garbage collection. Isn't it? That limits the point of time at which we can find the no. of live objects. – shanti Dec 26 '15 at 18:30
  • Above observation is correct. I have done what I recommended. Only on classes I design . Not for every class. I wanted to know how many of my classes were hanging around when program was running. – DaveTheRave Dec 26 '15 at 18:32
  • In the classes we developed. We would have a cleanup method as part of an abstract model. And our developers called that guy when they were done with object. – DaveTheRave Dec 26 '15 at 18:34
  • It's a quick way to get a gauge on counts without having to do much with runtime code analyses tools. – DaveTheRave Dec 26 '15 at 18:35
  • @DaveTheRave So what was the code in that method like, which made that method called everytime any object gets in a state of no reference pointing to it? – shanti Dec 26 '15 at 18:36
  • @VinceEmigh Actually I am fine with his answer, if it works. I just want to see a working example of the problem, even if I have to put my own customizations and put a few minor assumptions. – shanti Dec 26 '15 at 18:37
  • 1
    All our code for our classes had a cleanup method. Developers made sure to call when they were done with its use. I can whip up an example later today. I'm on my iPhone going to lunch.. the goal here is to make sure objects are indeed going away after use from memory .. Vs hanging around because of some unknown reference .. For example. Run your app. Thrn force garbage collection prior to final shutdown. Then dump the instance counts to see if they are really zero. It will tell a lot about how well u are cleaning up references in your app – DaveTheRave Dec 26 '15 at 18:46
  • @DaveTheRave Thanks Dave. I think I got your point. However the method being made to call manually by developer each time the object loses a reference, it looks a bit odd. First, the same object can have multiple references pointing to it (without invoking it's constructor). So how are you making sure that all references pointing to an object, starts pointing to null. Second thing, what if the developer forgets to manually call that method? Isn't it a way to automatically invoke that method? However, your answer looks promising, and I will try some codes out to see if I can find a way. – shanti Dec 26 '15 at 18:54
  • @VinceEmigh No. I am only concerned about my own developed classes. I have slightly edited the question to reflect the same. – shanti Dec 26 '15 at 18:55
  • @VinceEmigh No. Actually I mean to say that I want to find live objects only of user defined classes, not of the inbuilt java classes. But just want to add that, whatever user-defined classes are there, we can modify those to achieve this functionality. – shanti Dec 26 '15 at 19:06
  • I can lay something out the evening. U are on right track. – DaveTheRave Dec 26 '15 at 19:09
  • 1
    updated answer with some code. May need to be cleaned up or modified to fit your needs. Many ways to do synchronous.. decide whats best for you – DaveTheRave Dec 26 '15 at 23:56
  • Sorry for the late reply, and thanks for the code. But I don't think this will work if a new reference is pointed to an already created object. Because in that case, the constructor of the class won't be called. Let's say I wrote, ClassA obj = new ClassA(); ClassA objNew = obj; So in this case, how to make the second reference (objNew) accountable to it's creation (iCountInstances in this case)? – shanti Dec 27 '15 at 17:16
  • What we are counting is the number of instances of class. In your example. There is one class with two references to I – DaveTheRave Dec 27 '15 at 17:40
  • Are y trying to count references or instances? – DaveTheRave Dec 27 '15 at 17:43
  • trying to count objects not eligible for garbage collection. So you will have to factor in both the references, as well as instances I think. Because as long as there is even a single reference pointing to an object, it won't be eligible for garbage collection. But the program you have given, doesn't notice any reference being created just to point to an existing object. – shanti Dec 27 '15 at 17:46
  • I see what your trying to do here. The best we ever came up with. Without going to a run time analyzer is use this method.. Then periodically force gc and see the cleanupcount vs the finalize count.. They should be close. If not. Then ur code is pointing to something that u declared u don't need via cleanup method . – DaveTheRave Dec 27 '15 at 17:56
  • Ok thanks for all the help. It looks there is no easier solution other than using jmap, jhat, eclipse MAT etc. Let me look at these. – shanti Dec 27 '15 at 18:00