- Memory Analyzer (MAT) https://eclipse.org/mat/ oraz
- klasyczny jvisualvm Java SE.
Daruje sobie instrukcję jak korzystać z MAT - tego narzędzia da się używać bez specjalnej znajomości i pozwala w wielu wypadkach pokazać szybciej problem z pamięcią. Właściwie na rzecz tego bajeru zarzuciłem korzystanie jvisualvm dostępnego w Java SE od wersji 1.6. Spotkałem się jednak z kilkoma przypadkami kiedy nie potrafiłem dokładnie zbadać zawartości kolekcji lub zbioru obiektów przy pomocy zapytania OQL z MAT (oczywiście też posiada) Na wstępie dodam że całość publikacji jest właśnie poświęcam właśnie takiemu sposobowi exploracji Heap-a.
Czego używać do przeglądania i analizy?
- Zasadnicza zasada OQL dla MAT to nie ten sam co dla jvisualvm.
- MAT pod wieloma względami jest lepszy i szybszy niż jvisualvm
- jvisualvm ma OQL, który działa wolno jednak posiada porządne wsparcie dla wyrażeń javascript i tego właśnie mi brakuje (albo nie znam jak to użyć) w MAT
Dokumentacja OQL jvisualvm
Należy dokumentację traktować jak reference. W moim odczuciu pokazane przypadki użycia nie pokazuja tego że to jest JavaScript i co można tu zrobić. Przykłady koncentrują się na zapytaniu. Projekt można znaleźć w http://visualvm.java.net/ Aplikacja jednak jest bardzo podobna do standardowej dołączanej do java sun jdk1.7\bin\jvisualvm.exe http://visualvm.java.net/oqlhelp.html Podczas przeglądania znalazłem bardziej użyteczną dokumentację https://blogs.oracle.com/poonam/resource/OQL.htmPrzykłady użycia
Trywialne przypadki opisane w dokumentacji nie oddają użyteczności narzędzia. Lista wszystkich obiektów to za mało aby coś wiedzieć. Ale od tego się wszystko zaczyna trzeba mieć jakąś kolekcje którą chcemy explorować i filtrować.
Listowanie obiektów jakiejś klasy
select x from java.util.HashMap$Entry xZamiast tego można zrobić
select można się posłużyć heap.objects heap.objects("java.util.HashMap$Entry")
Listowanie String do pliku
Dla mnie osobiście to najbardziej użyteczny kawałek.Podam klika przypadków kiedy dostałem to co chciałem zobaczyć.
Przejrzeć to w MAT nie sposób, z poziomu opcji jest dostępna opcja copy i ona pozwala też exportować dane do pliku, ale nie przypadła mi do gustu. Dane nie są zapisywane w takim formacie który mnie interesuje.
Właśnie w jvisualvm znalazłem to co szukałem!
map(heap.objects("java.lang.String"),function(it) { return null != it ? it.toString() :"null"; }); var m = map(heap.objects("java.lang.String"),function(it) { return null != it ? it.toString() :"null"; }); var out = new java.io.BufferedWriter( new java.io.FileWriter("c:/temp/result14.txt", true) ); var i=0; out.write("id|wartosc\n"); while(m.hasMoreElements()) { var e=m.nextElement(); out.write(i+"|" + e.replace("\n"," ") + "\n"); out.flush(); i++; } out.close();W ten sposob do pliku mogę zapisać nawet gigabajty a potem w zewnętrznym sofcie sobie to policzyć (zagregować jak chce). OQL jest specyficzny i na razie te narzędzia są średnio wydajne.
Przeglądanie MapEntry
Kolejny przykład w którym dane z kolekcji lądują do pliku.var m = map(filter(heap.objects("java.util.HashMap$Entry"), 'null != it.key'),function(it) { return { k:it.key.toString(), vc:(it.value == null? "null": classof(it.value).name), v:(it.value != null?it.value.toString():"null") }; }); var out = new java.io.BufferedWriter( new java.io.FileWriter("c:/temp/result13.txt", true) ); var i=0; out.write("id|klucz|klasa|wartosc\n"); while(m.hasMoreElements()) { var e=m.nextElement(); out.write(i+"|" + e.k + "|" + e.vc + "|" + e.v + "\n"); out.flush(); i++; } out.close();Można wyeksportować elementy mapy do postacji id|klucz|klasa|wartosc
Obiekt po ID
Pobranie identyfikator obiektuselect objectid(o) from java.lang.Object oOdnalezienie obiektu po id
heap.findObject(32402378344)Dlaczego to może być użyteczne? Dlatego że gdy już mamy element z kolekcji zawsze możemy się do niego ponownie odwołać.
Dostęp do atrybutów obiektu
Nic prostszego. Wszystko to widać na bieżąco podczas oglądania obiektów.heap.findObject(32402378344).attributes.table
Listowanie elementów mapy
Normalnie pokazują się tylko wybrane pozycje z kolekcji. Gdy chcemy coś zobaczyć trzeba dodać do zapytania coś co pozwoli aby pokazało się te co chcemy... ale wtedy zapytanie musi wszystko przemielić a to trawa strasznie długo. Ja potrzebowałem przejrzeć mapę która miała 570000 pozycji. Nie udało mi się doczekać na to z OQL-a bezpośrednio. Tym sposobem no problem (oczywiście widać na bieżąco co leci do pliku)var t = heap.findObject(32402378344).attributes.table; var size1 = heap.findObject(32402378344).attributes.size; var out = new java.io.BufferedWriter( new java.io.FileWriter( "c:\temp\file_03.txt", true)); out.write("nr|object"); for (var i=0; i<size1; i++) { var e = t[i]; if (e==null) continue; var k=e.key; var v=e.value; if (k==null) {k="";} else {k = k.toString();}; if (v==null) {v="";} else {v = v.toString();}; out.write(i+"|"+ k.toString().replace("\n"," ") + "|" + v.toString().replace("\n"," ") +"\\n"); out.flush(); } out.close();
// lista contextow aplikacji
map(heap.objects("org.apache.catalina.loader.WebappClassLoader"),function(it) { return null != it ? it.canonicalLoaderDir.toString() :"null"; });
W Przypadku MAT
Zwracane obiekty z zapytania są określonego typu i można na ich rzecz również wywoływać metody
http://help.eclipse.org/juno/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Ftasks%2Fqueryingheapobjects.html
SELECT s.getClazz() FROM INSTANCEOF pl.kamsoft.common.monitor.KamMonitors s
SELECT s.resolveValue("timeMonitors") FROM INSTANCEOF pl.kamsoft.common.monitor.KamMonitors s
Brak komentarzy:
Prześlij komentarz