6 Replies Latest reply: Apr 30, 2007 8:20 AM by 807557 RSS

    Scoped Memory Reference Question

    807557
      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...
      public static void main(String[] args) {
                System.out.println("Welcome to RTSJ");
                ImmortalMemory memIm = ImmortalMemory.instance();
                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());
                               }
                          });
                          
                          AsyncEventHandler timerEvent = new AsyncEventHandler(){
                               public void 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());
                }
                
           }
        • 1. Re: Scoped Memory Reference Question
          807557
          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. Re: Scoped Memory Reference Question
            807557
            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. Re: Scoped Memory Reference Question
              807557
              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. Re: Scoped Memory Reference Question
                807557
                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. Re: Scoped Memory Reference Question
                  807557
                  That pretty much sums it up - yes. :)
                  • 6. Re: Scoped Memory Reference Question
                    807557
                    Thanks for the help so far David, I appreciate it! I have another
                    question in the works and will post it when I get a chance.

                    Michael