Ja jsem popisoval, jak se chova JVM za "normalnich" podminek. V okamziku, kdy zacne dochazet pamet, zacne JVM drsne optimalizovat. A ze to umi, lze videt na tomto prikladu (z Vaseho kodu jsem vypustil blok):

        System.out.println("start");
        // vytvorim Foo
        Foo f = new Foo(null);
        // vytvorim pole Stuff
        Stuff[] theStuffs = new Stuff[100000];
        for (int i = 0; i < theStuffs.length; i++) {
            theStuffs[i] = new Stuff();
        }
        // nez se dojde sem, je po objektu f
        while (true) {
            System.out.println("aaa");
            Runtime.getRuntime().gc();
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

Na mem pocitaci dojde k dealokaci objektu f jeste drive, nez se vstoupi do smycky while. Jak k tomu muze dojit? Java neco takoveho neumoznuje, jde ciste o optimalizaci JVM. Mimochodem, myslim, ze tohle je na hranici toho, co jeste lze delat, protoze kdyby nejaky program spolehal na to, ze objekt nemuze byt dealokovan pred koncem platnosti promenne f (tj. pred koncem metody), nebude fungovat.

Pokud jde o ty lokalni promenne, tak ve vypise javap je jejich pocet za retezcem Locals= a po dobu vykonavani metody se tato hodnota nemeni.

Z.T.
--
Zdenek Tronicek
Department of Computer Science and Engineering
Prague                   tel: +420 2 2435 7410
http://cs.felk.cvut.cz/~tronicek


Cituji Tomas Studva <[email protected]>:

Ahoj,
podla mna uz z vasho testovania vyplynulo, ze gc si da namahu uvolnit pamat co i len aj po jednom objekte - pripad ked ste nastavil f na null. Ja som skusil nastavit "s" na null a dopadlo to podla ocakavania, gc zrusil "s" aj obsiahnute "s.foo". Povedat ze gc uvolnuje lokalne premenne metod az po opusteni metody je hlupost, lebo potom pamatovo narocne metody by zjedli pamat aj keby uvolnovali referencie.

A tak som skusil toto:

       System.out.println("start");
       {
           // vytvorim Foo
           Foo f = new Foo(null);
           // vytvorim pole Stuff
           Stuff[] theStuffs = new Stuff[1000000];
           for (int i = 0; i < theStuffs.length; i++) {
               theStuffs[i] = new Stuff();
           }
       }
             // tu uz neexistuje nic
         while ( true ) {
               System.out.println("aaa");
               Runtime.getRuntime().gc();
               try {
                   Thread.sleep(200);
               } catch (InterruptedException e) {
                   // TODO Auto-generated catch block
                   e.printStackTrace();
               }
       }


Samozrejme ze gc pracoval a finalizoval. Trochu srandovny bol vystup niekde v strede:
finalize Stuff
finalize Stuff
finalize StuffException in thread "main" java.lang.OutOfMemoryError: Java heap space
   at java.lang.ref.Finalizer.register(Unknown Source)
   at java.lang.Object.<init>(Object.java:20)
   at Foo.<init>(Foo.java:6)
   at Stuff.<init>(Stuff.java:3)
   at Stuff.main(Stuff.java:18)

finalize Foo
finalize Foo

Nebudem to analyzovat, lebo to nebol vhodny priklad, pole je predsa nieco ine ako lokalne premenne. Spravny priklad by bol vytvorit tu metodu s naozaj desattisickami lokalnych premennych(cez makro by to slo).

T.S.



Odpovedet emailem