Java heap space

0

Mam samodzielną aplikację serwerową, która z klientami komunikuje się wykorzystując rmi, a jej baza danych to mysql.

Coś, gdzieś namotałem bo tak mniej więcej raz w tygodniu serwer rzuci parę razy:
Exception in thread "RMI TCP Connection(idle)" java.lang.OutOfMemoryError: Java heap space
potem na koniec:
Exception in thread "RMI RenewClean-[123.123.123.123:8000]" java.lang.OutOfMemoryError: Java heap space
i w końcu zdechnie.

W pierwszej chwili pomyślałem, że zwiększę stos i nara, ale z drugiej strony jak nie za tydzień to za dwa się wykrzaczy...

...wiec mam prośbę o jakiegoś linka do artykułu, albo wasze rady jak w ogóle zabrać się za szukanie końca tej pamięci?

0

Zadam to pytanie na jakim serwerze aplikacji stoi aplikacja?

0

Aplikacja jest samodzielna, a jedyny serwer w okolicy, nie licząc samej aplikacji, to debian ze standardowa sun-owską javą.

Skrócona idea działania: aplikacja wstaje, łączy się z baza, binduje obiekt odpowiedzialny za autoryzacje klientów i sobie działa. Klienci łączą się z aplikacją i po autoryzacji dostają kolejny obiekt odpowiedzialny za sesje itd.

Wiec tak sobie myślę, że pewnie tworze jakieś remote objects i one sobie żyją dopóki nie zjedzą całej pamięci, ale pewnie źle myślę bo co ma stos do tego?

0

OK. Bierzemy Eclipse TPTP, czyli profiler, i na nim odpalamy aplikację. Dobrze przygotować sobie zestaw testów. TPTP pokaże jakie obiekty ile czasu wiszą.

I jeszcze jedno jeżeli używasz bibliotek do XML to większość z nich lubi sobie czasaim spowodować wycieki pamięci.

0

Wiec z tymi obiektami to wyszło tak, że w kliencie miałem taki przypadek gdzie kończył on się mało elegancko (System.exit).

Gdy natomiast poprawiłem to na mniej więcej coś takiego, że przy zamykaniu klienta remote objects ustawiam na null, to wtedy faktycznie znikają one z serwera.

Jednak jak to jest? Jak klient zdechnie, albo sieć zdechnie, albo co tam innego zdechnie i nie zwolnie remote objects po stronie klienta to one nie znikną z serwera?

pÓÓÓÓki co żadnych testów nie pisałem, wszytko tak na oko, ale w profilerze to akurat najwięcej pamięci zajmują tablice byte[], które pojęcia nie mam skąd się biorą, bo ja wprost takowych nie deklaruje. Nie używam też żadnych bibliotek oprócz mysl-connectora.

0

Tablice to właśnie obiekty zdalne po serializacji, gotowe do wysłania do klienta.

Generalnie w uproszczeniu rzecz polega na tym, że JVM serwera tworząc obiekt oznacza go jako zdalny i przekazuje zarządzanie jego stanem do JVM klienta. JVM klienta wykorzystuje ten obiekt i jeżeli GC klienta postanowi usunąć obiekt to JVM klienta wysyła do JVM serwera sygnał by ten usunął obiekt. Cała komunikacja opiera się zatem o wymianę komunikatów, ale JVM serwera nie monitoruje stanu JVM klienta nie ma możliwości usunięcia obiektu po padzie JVM klienta. (opis: http://www.freepatentsonline.com/7203756.html)

Rozwiązanie w miarę proste to po stronie klienta nullowanie obiektów zdalnych w metodzie finalize() (nie jest to pewne rozwiązanie, ale w miarę proste). Niestety nadal pozostaje problem nagłego wyłączenia klienta :(

0
Koziołek napisał(a)

(...)
Generalnie w uproszczeniu rzecz polega na tym, że JVM serwera tworząc obiekt oznacza go jako zdalny i przekazuje zarządzanie jego stanem do JVM klienta. JVM klienta wykorzystuje ten obiekt i jeżeli GC klienta postanowi usunąć obiekt to JVM klienta wysyła do JVM serwera sygnał by ten usunął obiekt. Cała komunikacja opiera się zatem o wymianę komunikatów, ale JVM serwera nie monitoruje stanu JVM klienta nie ma możliwości usunięcia obiektu po padzie JVM klienta. (opis: http://www.freepatentsonline.com/7203756.html)
(...)

Na stronie Suna znalazłem taki fragment (http://java.sun.com/developer/onlineTraining/rmi/RMI.html):
"In addition to the reference counting mechanism, a live client reference has a lease with a specified time. If a client does not refresh the connection to the remote object before the lease term expires, the reference is considered to be dead and the remote object may be garbage collected. The lease time is controlled by the system property java.rmi.dgc.leaseValue. The value is in milliseconds and defaults to 10 minutes."

Z tego wynikało by, że JVM serwera ma jednak możliwość usunięcia obiektu.

0

Hm... pytanie zatem gdzie się to konfiguruje i dlaczego u @abe nie działało w trybie domyślnym.

0

Dzięki za rozjaśnienie tematu.

Faktycznie jak ustawie java.rmi.dgc.leaseValue, to serwer usunie remote object dokładnie po takim czasie jaki wprowadzę (choć akurat garbage collector'a wymuszam ręczenie w profilerze - ale stawiam że sam też by się kiedyś obudził i posprzątał).

Nie wpłynęło to zbytnio na rozmiar wspomnianych przeze mnie tablic, które zajmują najwięcej pamięci, ale jest wielce prawdopodobne, że jeszcze coś innego mam namieszane w aplikacji.

Co do ustawień domyślnych - testowałem to wszytko na lokalnej maszynie i całkiem możliwe, że coś tu miałem przekombinowane z ustawieniami, ale czy jest możliwe uruchomienie aplikacji na docelowym serwerze (debianie) wraz z profilerem, a lokalnie oglądanie sobie pracy poprzez jakieś IDE (eclipse, netbeans)?

0

Dwa słowa: Dużo zabawy.

Wszystko zależy od profilera. http://www.eclipse.org/tptp/home/documents/tutorials/profilingtool/profilingexample_32.html na samym końcu strony o podpięciu się do zdalnego serwera za pomocą TPTP.

1 użytkowników online, w tym zalogowanych: 0, gości: 1