Scoped Memory Reference Question
What I think I am doing:
Getting and instance of immortal mem.
Running logic that puts an event handler, a periodic timer, and the logic for the event
handler in immortal memory (out of the GC reach). Showing the memory consumed
for the scopedA secion, and the immortal memory.
The object is to use the scoped memory for the leaky console output, ensuring that
objects created for the console output are all deallocated when the enter logic for the async handler exits.
The way I think it is set up is that the Timer, the asynceventhandler and the actual logic
for the scopedA run are all in immortal memory. When the async event is fired, the scopedA area is allocated and the System.out.println executes from there.
stack:
heap
immortalMemory ( scopeA ref, asyncEventHander, PeriodicTimer)
scopedA ( entered to make the leaky System.out.println)
immortalMemory
The original question was why does the LTMemory scopedA reference have to be
outside the run logic, while the asyncEventHandler reference passed to the Periodic timer does not. I assum that the scopedA reference is in immortal memory.
I believe that I could put the new LTMemory() call outside the run logic and then
use the same scoped memory each time, without having to suffer the time needed to create the LTMemory area each time the asyncEvent Handler runs...
publicstaticvoid main(String[] args){
System.out.println("Welcome to RTSJ");
ImmortalMemory memIm = ImmortalMemory.instance();
memIm.enter(new Runnable(){
LTMemory scopedA;
publicvoid run(){
scopedA =new LTMemory(1024,1024,new Runnable(){
publicvoid run(){
System.out.println("TimerEvent " + scopedA.memoryConsumed());
}
});
AsyncEventHandler timerEvent =new AsyncEventHandler(){
publicvoid handleAsyncEvent(){
scopedA.enter();
}
};
PeriodicTimer pt =new PeriodicTimer(
new RelativeTime(0,0),
new RelativeTime(1000,0),
timerEvent );
pt.start();
}
});
for(int i = 0; i < 20; i++){
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
System.out.println(memIm.memoryConsumed());
}
}
[3555 byte] By [
mgarretta] at [2007-11-27 2:45:29]

# 1
> The way I think it is set up is that the Timer, the
> asynceventhandler and the actual logic
> for the scopedA run are all in immortal memory.
Right. The LTMemory instance, then Runnable instance, the AsyncEventHandler instance and the PeriodicTimer instance are all allocated in immortal. As are the two time objects. Every "new" within that run() method occurs in Immortal memory.
> When the async event is fired, the scopedA area is
> allocated and the System.out.println executes from
> there.
The scopedA area isn't "allocated" when the event fires, it is allocated in the run() method that is executed in immortal. When the event fires and the handler is released then it enters scopedA and the println is executed from there. When that completes the scope is left and as it is no longer in use the memory for that scope will be reclaimed. So next time the event fires it will enter the scope again and find an empty scope.
> original question was why does the LTMemory scopedA
> reference have to be outside the run logic, while the
> asyncEventHandler reference passed to the Periodic timer does not.
It doesn't have to be, but if it isn't then it has to be declared final because it is being accessed by the annonymous inner class you defined for your AsyncEventHandler. That's just a rule of inner classes: they can access local variables in the enclosing scope (that's Java language syntactic scope not "scope memory"), but those local variables must be final.
> I believe that I could put the new LTMemory() call
> outside the run logic and then
> use the same scoped memory each time, without having
> to suffer the time needed to create the LTMemory area
> each time the asyncEvent Handler runs...
You could put it outside the run() logic, but it won't change anything. Your run() logic is only executed once because you only enter immortal once. So you are using the same scoped memory each time.
# 2
Thanks for the quick reply!!
> The scoped area isn't "allocated" when the event
> fires, it is allocated in the run() method that is
> executed in immortal. When the event fires and the
> handler is released then it enters scopedA and the
> println is executed from there. When that completes
> the scope is left and as it is no longer in use the
> memory for that scope will be reclaimed. So next time
> the event fires it will enter the scope again and
> find an empty scope.
Time for my Java lesson.. (I am relativeley new to Java!).
memIm.enter(new Runnable(){
LTMemory scopedA;
public void run(){
scopedA = new LTMemory(1024,1024, new Runnable(){
public void run(){
System.out.println("TimerEvent " + scopedA.memoryConsumed());
}
});
Here, the Runnable instance is an anonymous class that looks
something like this:
class Anonymous implements Runnable {
LTMemory scopedA;
public void run(){
// allocate object out of Immortal Memory
scopedA = new LTMemory(1024,1024, new Runnable {
public void run(){
logic for execution from scoped memory,
Where are the byte codes for this logic?
Object allocated by new, exist in scopedA memory.
}
}
// create other instances
}
}
This first anonymous class is created in Immortal memory, and remains there with the scopedA reference, referencing the SCoped a object. This object is created in immortal memory. I would surmise here, that the actual physical memory has not been allocated, and will
be allocated each time the memory area is entered. Then when the
enter is complete, and the scopedA reference count goes to 0, the
memory is 'free' ed, with the scopedA object still sitting in Immortale
memory, for use on the next enter call.
> It doesn't have to be, but if it isn't then it has to
> be declared final because it is being accessed by the
> annonymous inner class you defined for your
> AsyncEventHandler. That's just a rule of inner
> classes: they can access local variables in the
> enclosing scope (that's Java language syntactic scope
> not "scope memory"), but those local variables must
> be final.
I might be doing something wrong but I can not seem to get it
to work inside the run method, even when declared final. I do
now undestand the difference between scopedA being referenced
inside the inner class.
>
> You could put it outside the run() logic, but it
> won't change anything. Your run() logic is only
> executed once because you only enter immortal once.
> So you are using the same scoped memory each time.
Got it!
Thanks!
Michael
# 3
> I would surmise here, that the actual physical memory has not been
> allocated, and will be allocated each time the memory area is entered.
Not normally. When you create a ScopedMemory object (LTMemory or VTMemory) the backing store (or at least the minimum size backing store) is usually allocated at the same time. When you enter the scope you start allocating in the backing store - if only the minimum was pre-allocated and you try to go beyond that, it will try to grow and if it fails then you'll get an OutOfMemoryError. When you exit the scope, and noone else is using it, then the backing store is marked as being empty so that the next time an enter occurs it starts allocating with an empty backing store. (Of course finalization of the objects occurs first etc).
The actual backing store will probably not be freed until the scoped memory object itself is reclaimed.
In theory an implementation could allocate and free the backing store as you surmised *but* once the scoped memory area has been constructed it has to be guaranteed that the minimum size backing store is available. That would be a difficult guarantee to make in general, so implementations tend to allocate up front.
# 4
So the Physical memory is allocated upon creation of the
LT or VT object, with the minimum amount of memory specified.
Upon entry, objects created are stored in the scoped memory,
if attempted allocations, are greater than the min, more memory
will be allocated (if possible) up to the max.
Upon exit of the entry, all objects are 'deallocated' making the full
area available upon the next entry. So in my example the memory
stack looks like this:
heap <- imortal <- scopedA
ScopedA is always available to enter into, or execute in. scopedA will
only actually be 'finalized?' (deallocated) when its reference is invalid, and only if something is there to clean it up, like having it nested in another scoped area or having it on the heap. If the reference is in immortal, its there forever.
I think..
mcg
# 5
That pretty much sums it up - yes. :)
# 6
Thanks for the help so far David, I appreciate it! I have anotherquestion in the works and will post it when I get a chance.Michael