- 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