2011-11-11 9 views
5

Mam monitorować aplikację java z profilerem, aby poznać wyciek pamięci. I mam klasę, która bierze prawie 80% pamięci, która jestJak zwiększyć priorytet programu FinalizerThread do zbierania obiektów w GC

java.lang.ref.Finalizer 

Potem google to do powyższej klasy i znaleźć ciekawy artykuł http://www.fasterj.com/articles/finalizer1.shtml

Teraz może ktoś zasugerować mi jak mogę zwiększyć priorytet FinalizerThread do zbierać te obiekty w GC.

Jeszcze jedno jestem w obliczu tego problemu w systemie Linux z jądrem w wersji Linux 2.6.9-5.ELsmp (i386) i Linux 2.6.18-194.17.4.el5 (i386) ale to działa dobrze (bez błędu OOM) na Linux 2.6.18-128.el5PAE (i386).

Czy to jest problem z powodu jądra systemu Linux? Czy istnieje dowolna zmienna JVM w celu ulepszenia priorytetu programu FinalizerThread?

Thanx z góry.

+1

Dobre pytanie, myślę, że ogólnie potrzebujesz zminimalizować użycie Finalizerów. –

+0

Być może w trybie PAE masz po prostu więcej pamięci (poza PAE jest ograniczona do 4 GB) - sprawdź "free". Nie sądzę, że tutaj działa wersja jądra. –

+0

Dzięki Dan, Jak sugeruje Peter poniżej, sprawdzam teraz system plików. – user1041580

Odpowiedz

2

Aby odpowiedzieć na pytanie dosłownie, możesz to zrobić. Jednak, jak przedstawiono poniżej, prawdopodobnie nie ma sensu, szczególnie, że wątek ma już wysoki priorytet.

for(Thread t: Thread.getAllStackTraces().keySet()) 
    if (t.getName().equals("Finalizer")) { 
     System.out.println(t); 
     t.setPriority(Thread.MAX_PRIORITY); 
     System.out.println(t); 
    } 

drukuje

Thread[Finalizer,8,system] 
Thread[Finalizer,10,system] 

chyba że używasz 100% wszystkich rdzeni, lub blisko niego, priorytetem nie ma znaczenia, ponieważ nawet najniższy priorytet będzie uzyskać jak najwięcej CPU jak chce.

Uwaga: W systemie Linux ignoruje podwyższone priorytety, chyba że jesteś rootem.

Zamiast tego należy zmniejszyć pracę wykonaną przez finalizatora. Idealnie nie powinno to mieć nic wspólnego. Jedną z przyczyn dużego obciążenia w finalizatorze jest tworzenie zasobów, które powinny zostać zamknięte, ale są odrzucane. (pozostawiając finalizator zamiast zamykać zasób)

Krótko mówiąc, powinieneś spróbować określić, które zasoby są finalizowane i upewnić się, że nie trzeba nic robić, gdy wywoływana jest metoda finalize(), najlepiej nie używać ta metoda w ogóle.

Jest możliwe, że zasoby trwają dłużej, aby zamknąć starszą wersję jądra systemu Linux. Sprawdziłbym, czy sprzęt jest identyczny, ponieważ może to oznaczać, że potrzeba więcej czasu na wyczyszczenie zasobów. (Ale prawdziwą poprawką jest upewnienie się, że nie musi tego robić)

+0

Czy java może coś zmienić. Ponieważ pierwsze dwa systemy Linux (gdzie pojawia się problem z OOM), używam 64-bitowego języka Java i takiego, który działa dobrze, używam 32-bitowego? – user1041580

+0

Wersja Java, niezależnie od tego, czy używasz 64-bitowego, czy 32-bitowego, jakiego sprzętu używasz: procesor, pamięć, dysk, przepustowość sieci, obciążenie, np. czy wykonuje inną pracę, jak bardzo zajęty jest zamykanie zasobów, np. jeśli połączą się z bazą danych lub usługą, wszystkie będą miały znaczenie w tym przypadku. Wersja jądra może zrobić różnicę, ale najpierw sprawdziłbym pierwszą listę. –

+0

Jeśli masz starszą wersję Java, wersja 64-bitowa może korzystać z większej ilości pamięci niż wersja 32-bitowa. Jeśli masz najnowszą wersję, różnica jest znacznie mniejsza (ponieważ używa '-XX: + UseCompressedOops') Prawdziwą poprawką jest naprawienie kodu, a nie majsterkowanie z maszyną JVM. –

2

Wątek finalizatora rzadko powinien dawać dużo pracy. Zasoby powinny już zostać wydane. Upewnij się, że Twój kod obsługuje zasoby w standardowy sposób.

Java SE 7:

try (final Resource resource = acquire()) { 
    use(resource); 
} 

Pre-Java SE 7:

final Resource resource = acquire(); 
try { 
    use(resource); 
} finally { 
    resource.release(); 
} 
0

Jak Tom Hawtin zwraca uwagę, można zdobyć na FinalizerThread tworząc finalize() metodę, która wywołuje Thread.currentThread() i następnie przechowuje to w statycznym. Prawdopodobnie również możesz zmienić jego priorytet.

Ale istnieje duża szansa, że ​​nie przyniesie to żadnego pożytku. Prawdopodobnie istnieje tylko jeden wątek finalizatora. A problem jest prawdopodobne, że albo:

  • wątek nie może nadążyć, ponieważ jest po prostu zbyt dużo pracy do zrobienia, albo
  • wątek jest blokowany przez coś robisz w finalizatora metody.

(I będę oczekiwać wątek finalizator do już być oznaczone jako wysoki priorytet.)

Ale tak czy inaczej, myślę, że lepszym rozwiązaniem jest pozbycie się z metod finalize(). Założę się, że robią coś, co jest albo niepotrzebne ... albo podejrzane. W szczególności używanie finalizatorów do odzyskiwania zasobów z upuszczonych obiektów jest złym sposobem na rozwiązanie tego konkretnego problemu. (Patrz odpowiedź Toma Hawtina).

+0

Zdobądź obiekt wątku finalizatora? Łatwo. Stwórz obiekt ze sfinalizatorem, który przechowuje 'Thread.currentThread()' w statycznym. –

Powiązane problemy