I'm trying to create my own pattern (or something similar to a pattern I guess) where objects that are anonymously instantiated can still be referenced, but I'm getting weird memory results. It seems as if the free memory is decreasing when it should be increasing--

import java.util.ArrayList;

public class SelfTracker{

	private final static ArrayList<SelfTracker> track = new ArrayList<SelfTracker>(0);
	private int index = 0;
	private static int trackCount = 0;

	public SelfTracker(){
		index = trackCount++;
		track.add(this);
	}

	/**
	 * Shortcut way of printing the data in the track
	 */
	public static void printData(){
		System.out.println(track);
	}

	/**
	 * Clears the tracker, and then calls the garbage
	 * collector to remove the (supposedly) untracked
	 * objects from being used in heap memory.
	 */
	public static void releaseAll(){
		track.clear(); // Assuming that the references of the ArrayList will be pointint to null
		Runtime.getRuntime().gc(); // gets the current Runtime and attempts to garbage-collect unpointed references
								   // (not reliable)
	}

	/**
	 * Simply prints a message when this method is called.
	 */
	@Override protected void finalize() throws Throwable{
		System.out.println("Releaseing object: " + this);
		super.finalize();
	}

	/**
	 * Just overriding the toString method in the base class
	 */
	@Override public String toString(){
		return "SelfTracker at address: " + super.toString().toUpperCase() +
			   "\n with index: " + index;
	}

	public static void main(String... args){

		Runtime rt = Runtime.getRuntime(); // getting a handle on the current runtime for this JVM
		rt.gc(); // for accuracy
		System.out.println(rt.freeMemory() + " / " + rt.totalMemory()); // printing the freeMEM/totalMEM
		new SelfTracker(); // no other reference other than static track
		new SelfTracker(); // ditto
		new SelfTracker(); // ditto
		System.out.println(rt.freeMemory() + " / " + rt.totalMemory()); // oddly no change in memory?
		SelfTracker.printData(); // printing the data in the track
		SelfTracker.releaseAll(); // I'm trusting the definition of ArrayList's "clear" to set its list-references to null

		/*
		   Assumption - nothing was pointing to the objects after they were cleared from ArrayList.
		   They should be garbage collected.
		 */

		System.out.println(rt.freeMemory() + " / " + rt.totalMemory()); // free memory decreases!
	}
}

Recommended Answers

All 9 Replies

these are the results i got from running in bluej are they similar to yours?

for some reason the last call to println() didn't do anything, i don't have an explanation for that though.

64979064 / 65470464
64979064 / 65470464
[SelfTracker at address: SELFTRACKER@15E234C
 with index: 0, SelfTracker at address: SELFTRACKER@15F7107
 with index: 1, SelfTracker at address: SELFTRACKER@F593AF
 with index: 2]
65007096 / 65470464
Releaseing object: SelfTracker at address: SELFTRACKER@F593AF
 with index: 2
Releaseing object: SelfTracker at address: SELFTRACKER@15F7107
 with index: 1
Releaseing object: SelfTracker at address: SELFTRACKER@15E234C
 with index: 0

a second run:

64868880 / 65470464
64868880 / 65470464
[SelfTracker at address: SELFTRACKER@61736E
 with index: 0, SelfTracker at address: SELFTRACKER@1E13E07
 with index: 1, SelfTracker at address: SELFTRACKER@AF72D8
 with index: 2]
65141432 / 65470464
Releaseing object: SelfTracker at address: SELFTRACKER@AF72D8
 with index: 2
Releaseing object: SelfTracker at address: SELFTRACKER@1E13E07
 with index: 1
Releaseing object: SelfTracker at address: SELFTRACKER@61736E
 with index: 0

Yours has somewhat correct results, but I'm not getting that.

See attached to see what I'm getting--

weird, i get the same type of results as your from the command prompt
[ATTACH]6893[/ATTACH]

huh i cannot explain that, when bluej runs it through it's virtual machine it must be doing something different than when the call to java SelfTracker runs a new VM

with netbeans i get this which works the same as the command prompt

5041312 / 5177344
5041312 / 5177344
[SelfTracker at address: DANIWEBHELP.SELFTRACKER@19821F
 with index: 0, SelfTracker at address: DANIWEBHELP.SELFTRACKER@ADDBF1
 with index: 1, SelfTracker at address: DANIWEBHELP.SELFTRACKER@42E816
 with index: 2]
5041096 / 5177344
Releaseing object: SelfTracker at address: DANIWEBHELP.SELFTRACKER@42E816
 with index: 2
Releaseing object: SelfTracker at address: DANIWEBHELP.SELFTRACKER@ADDBF1
 with index: 1
Releaseing object: SelfTracker at address: DANIWEBHELP.SELFTRACKER@19821F
 with index: 0

If you look at a heap dump taken on the last line of main(), at which you print the memory, you'll see where that extra memory is going:

There is a lot of stuff on the heap beyond those three objects you are looking at.

ok, but why would bluej do things differently?

If you look at a heap dump taken on the last line of main(), at which you print the memory, you'll see where that extra memory is going:
[ATTACH]6896[/ATTACH]
There is a lot of stuff on the heap beyond those three objects you are looking at.

Do you mean to tell me that the call to printing the ArrayList in turn calls the toString of each element and therefore--

@Override public String toString(){
return "SelfTracker at address: " + super.toString().toUpperCase() +
"\n with index: " + index;
}

-- exists in memory and is responsible for making my results inaccurate?

That would make sense if its true.

> ok, but why would bluej do things differently?

I really couldn't say. Netbeans and BlueJ both are interacting with the JVM when they run your program and freememory and totalmemory make no distinctions about the specifics or source of that allocation. If you want to examine the specifics you need to be working with heap dumps instead of raw aggregate memory numbers like those.

Alex, the point was to keep in mind that other classes in the JDK, such as Runtime, System, the class loader, etc. are also allocating and using objects and primitives internally. The total memory reflects all of those things, not just the ones you are creating in your own code directly.

Alex, the point was to keep in mind that other classes in the JDK, such as Runtime, System, the class loader, etc. are also allocating and using objects and primitives internally. The total memory reflects all of those things, not just the ones you are creating in your own code directly.

I'll be more aware of this next time. Thank you Ezzaral and sciwizeh.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.