Я попытался изменить указатель класса на объект, чтобы он указывал на другой класс с идентичной настройкой.Чтобы быть точным, для моего теста я использовал копию исходного класса с измененным методом toString()
, просто чтобы распечатать что-то еще.
Предполагая, что JVM упорядочивает атрибуты одинаково в объектах памяти двух классов, они должны выглядеть одинаково.
Таким образом, в моем тесте я получил указатель klass из объекта нового класса и установил объект старого, оригинального класса.После вызова toString()
я увидел новый вывод, как и ожидалось.
Однако, когда я делал это в цикле, JVM зависала.Я попытался создать new Test()
объекты и изменил указатель класса так, чтобы он указывал на Test2
следующим образом (примечание: сжатый 64-битный ООП):
int test2KlassIdentifier = unsafe.getInt(test2Obj, 8L);
unsafe.putInt(testObj, 8L, test2KlassIdentifier);
После создания сотен тысяч объектов я получил дамп ядра:
# Internal Error (C:\ojdkbuild\lookaside\java-1.8.0-openjdk\hotspot\src\share\vm\opto\memnode.cpp:906), pid=27120, tid=0x0000000000009374
# assert(!(adr_type->isa_oopptr() && adr_type->offset() == oopDesc::klass_offset_in_bytes())) failed: use LoadKlassNode instead
Затем я уменьшил число, чтобы создать только 100.000 -> без дампа ядра, пока не создал кучу new Object()
с.
Так что я чувствую, что это проблема, связанная с ГК, и что мои изменения испортили что-то внутри.Однако я хотел бы понять, чем мой «пропатченный» объект отличается от вновь созданного объекта типа Test2