2015-05-07 40 views
7

Próbuję śledzić przydziały wszystkich obiektów w JVM.Dodawanie invokestatic do java/lang/Object. <init> za pośrednictwem agenta JVM TI powoduje awarię maszyny JVM z użyciem segmentfault

W kilku dokumentach około profilers rozdziału wspomniano, że najprostszym sposobem na to jest taka: dodać invokestatic Tracker.trackAllocation()V dyspozycję java/lang/Object.<init> (zazwyczaj składa się z pojedynczej instrukcji return, dodajemy invokestatic przed nim, więc jest to 2 instrukcje teraz).

(Wiem, że to podejście jest powolne i nie będzie śledzić alokacji tablicy, ale chciałem zacząć od najprostszego rozwiązania .Nie przekazuję też odniesienia do przydzielonego obiektu do śledzenia, ale zostanie ono dodane później).

Plik klasy jest instrumentowany z agentem JVM TI w haczyku onClassLoaded.

Jednak po dodaniu instrukcji JVM JVM ulega awarii wraz z segfault. Obiekt śledzenia został dodany do programu ładującego klasy bootstrap, więc powinien być widoczny na dowolnym etapie. Próbowałem dodać nop zamiast invokestatic, a JVM działa poprawnie ze zmodyfikowaną klasą Object. Problem polega więc na wywołaniu jakiejś statycznej metody.

Próbowałem również aplikować na instrumentach (nie w ramach bazy) i działało dobrze - został wywołany tracker i nie doszło do awarii. Próbowałem także przedefiniować obiekt w 2 punktach: kiedy jest on początkowo załadowany (pierwsza załadowana klasa) lub po zdarzeniu vmInit (gdy wszystkie klasy bazowe są załadowane, a ograniczenia na jni są podnoszone).

Czy jest coś, czego mi brakuje o instrumentowaniu java.lang.Object?

Kod dla agenta jest tutaj: https://gist.github.com/Korobochka/3bf2f906f6ab85b22dec (Sprawdzanie błędów jest usuwany, kod do zmiany zajęcia również nie jest w cenie, ale to działa na tyle dobrze, dla innych klasach)

+0

Pokaż nam kod – apangin

+0

@apangin Dodałem istotę z kodem agenta na dole pytania. Jest to wersja, w której obiekt zmienia się po vmInit. – Korobochka

+1

Myślę, że problem polega na tym, że klasa "Tracker" to sam obiekt, który musi zostać utworzony przed utworzeniem obiektu, ale to wymagałoby najpierw załadowania klasy ... i tak dalej. Musisz jakoś przerwać ten cykl. – biziclop

Odpowiedz

5

Wygląda na to, że problem jest w nazywaniu System.out.println z LeakAgentInterface. Po pierwsze, System.out może nie zostać jeszcze zainicjalizowany. Po drugie, println może przydzielać same obiekty.

+1

Dotyczy to również "String", który zostanie wydrukowany, co również jest przedmiotem; nawet stała w czasie kompilacji 'String' muszą być przydzielone w czasie wykonywania, kiedy są używane po raz pierwszy ... – Holger

+0

Właśnie sprawdzone, tak jest w rzeczywistości. Dziękuję Ci bardzo!Zmarnowałem kilka dobrych godzin, a błąd był bardzo prosty i głupi. (Ale szukałem tylko błędu w kodzie C++. – Korobochka