LINUX.ORG.RU

История изменений

Исправление svr4, (текущая версия) :

package main;

class PublicMorozov
{
  // заготавливаем инстанс, для которого мы будем создавать экземпляр inner класса
  private static final PublicMorozov INSTANCE = new PublicMorozov();
  // и поле, содержимое которого и будем заменять
  private static final java.lang.ref.WeakReference<Inner> targetField = new java.lang.ref.WeakReference<Inner>(null);

  private class Inner
  {}

  public PublicMorozov()
  {}

  public static void makeReplace() throws Exception
  {
    // получаем через рефлект поле, которое предстоит заменить
    java.lang.reflect.Field targetAsField = Class.forName("main.PublicMorozov").getDeclaredField("targetField");
    // снимаем с него private
    targetAsField.setAccessible(true);

    // получаем адрес поля модификаторов в целевом поле
    java.lang.reflect.Field modifiers = Class.forName("java.lang.reflect.Field").getDeclaredField("modifiers");
    // снимаем с него private
    modifiers.setAccessible(true);

    // снимаем с целевого поля private и final, а вместо них ставим public
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.PRIVATE);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() | java.lang.reflect.Modifier.PUBLIC);

    // но всё не так просто... если попытаться применить изменения то нас может отправить куда подальше с IllegalAccessException
    // поэтому мы заменяем accessor на свой, которому будет пофиг на финал
    // мы используем именно overrideFieldAccessor поскольку поле изначально было private, в противном случае следует использовать fieldAccessor
    java.lang.reflect.Field accessorField = Class.forName("java.lang.reflect.Field").getDeclaredField("overrideFieldAccessor");
    // как обычно снимаем с него private
    accessorField.setAccessible(true);
    // поскольку мы заменяем статический Object нам нужен именно этот тип, их много под разные типы полей и данных
    java.lang.reflect.Constructor accessorConstructor = Class.forName("sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl").getDeclaredConstructor(java.lang.reflect.Field.class, boolean.class);
    // конструктор тоже сокрыт... но разве нас этим испугаешь?
    accessorConstructor.setAccessible(true);
    // вот теперь всё нормально - новый accessor на поле final и смотреть не будет
    accessorField.set(targetAsField, accessorConstructor.newInstance(targetAsField, false));

    // и на десерт - доступ к inner классу
    java.lang.reflect.Constructor innerConstructor = Class.forName("main.PublicMorozov$Inner").getDeclaredConstructor(Class.forName("main.PublicMorozov"));
    innerConstructor.setAccessible(true);

    // заменяем таки содержимое нужного поля
    targetAsField.set(null, new java.lang.ref.WeakReference<Inner>((Inner) innerConstructor.newInstance(INSTANCE)));
  }
}

В плюсах обычно Паблика кастуют проще: #define private public

Исправление svr4, :

package main;

class PublicMorozov
{
  // заготавливаем инстанс, для которого мы будем создавать экземпляр inner класса
  private static final PublicMorozov INSTANCE = new PublicMorozov();
  // и поле, содержимое которого и будем заменять
  private static final java.lang.ref.WeakReference<Inner> targetField = new java.lang.ref.WeakReference<Inner>(null);

  private class Inner
  {}

  public PublicMorozov()
  {}

  public static void makeReplace() throws Exception
  {
    // получаем через рефлект поле, которое предстоит заменить
    java.lang.reflect.Field targetAsField = Class.forName("main.PublicMorozov").getDeclaredField("targetField");
    // снимаем с него private
    targetAsField.setAccessible(true);

    // получаем адрес поля модификаторов в целевом поле
    java.lang.reflect.Field modifiers = Class.forName("java.lang.reflect.Field").getDeclaredField("modifiers");
    // снимаем с него private
    modifiers.setAccessible(true);

    // снимаем с целевого поля private и final, а вместо них ставим public
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.PRIVATE);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() | java.lang.reflect.Modifier.PUBLIC);

    // но всё не так просто... если попытаться применить изменения то нас может отправить куда подальше с IllegalAccessException
    // поэтому мы заменяем accessor на свой, которому будет пофиг на финал
    // мы используем именно overrideFieldAccessor поскольку поле изначально было private, в противном случае следует использовать fieldAccessor
    java.lang.reflect.Field accessorField = Class.forName("java.lang.reflect.Field").getDeclaredField("overrideFieldAccessor");
    // как обычно снимаем с него private
    accessorField.setAccessible(true);
    // поскольку мы заменяем статический Object нам нужен именно этот тип, их много под разные типы полей и данных
    java.lang.reflect.Constructor accessorConstructor = Class.forName("sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl").getDeclaredConstructor(java.lang.reflect.Field.class, boolean.class);
    // конструктор тоже сокрыт... но разве нас этим испугаешь?
    accessorConstructor.setAccessible(true);
    // вот теперь всё нормально - новый accessor на поле final и смотреть не будет
    accessorField.set(targetAsField, accessorConstructor.newInstance(targetAsField, false));

    // и на десерт - доступ к inner классу
    java.lang.reflect.Constructor innerConstructor = Class.forName("main.PublicMorozov$Inner").getDeclaredConstructor(Class.forName("main.PublicMorozov"));
    innerConstructor.setAccessible(true);

    // заменяем таки содержимое нужного поля
    targetAsField.set(null, new java.lang.ref.WeakReference<Inner>((Inner) innerConstructor.newInstance(INSTANCE)));
  }
}

В плюсах обычно Паблика кастуют проще:

#define private public

Исходная версия svr4, :

package main;

class PublicMorozov
{
  // заготавливаем инстанс, для которого мы будем создавать экземпляр inner класса
  private static final PublicMorozov INSTANCE = new PublicMorozov();
  // и поле, содержимое которого и будем заменять
  private static final java.lang.ref.WeakReference<Inner> targetField = new java.lang.ref.WeakReference<Inner>(null);

  private class Inner
  {}

  public PublicMorozov()
  {}

  public static void makeReplace() throws Exception
  {
    // получаем через рефлект поле, которое предстоит заменить
    java.lang.reflect.Field targetAsField = Class.forName("main.PublicMorozov").getDeclaredField("targetField");
    // снимаем с него private
    targetAsField.setAccessible(true);

    // получаем адрес поля модификаторов в целевом поле
    java.lang.reflect.Field modifiers = Class.forName("java.lang.reflect.Field").getDeclaredField("modifiers");
    // снимаем с него private
    modifiers.setAccessible(true);

    // снимаем с целевого поля private и final, а вместо них ставим public
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() & ~java.lang.reflect.Modifier.PRIVATE);
    modifiers.setInt(targetAsField, targetAsField.getModifiers() | java.lang.reflect.Modifier.PUBLIC);

    // но всё не так просто... если попытаться применить изменения то нас может отправить куда подальше с IllegalAccessException
    // поэтому мы заменяем accessor на свой, которому будет пофиг на финал
    // мы используем именно overrideFieldAccessor поскольку поле изначально было private, в противном случае следует использовать fieldAccessor
    java.lang.reflect.Field accessorField = Class.forName("java.lang.reflect.Field").getDeclaredField("overrideFieldAccessor");
    // как обычно снимаем с него private
    accessorField.setAccessible(true);
    // поскольку мы заменяем статический Object нам нужен именно этот тип, их много под разные типы полей и данных
    java.lang.reflect.Constructor accessorConstructor = Class.forName("sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl").getDeclaredConstructor(java.lang.reflect.Field.class, boolean.class);
    // конструктор тоже сокрыт... но разве нас этим испугаешь?
    accessorConstructor.setAccessible(true);
    // вот теперь всё нормально - новый accessor на поле final и смотреть не будет
    accessorField.set(targetAsField, accessorConstructor.newInstance(targetAsField, false));

    // и на десерт - доступ к inner классу
    java.lang.reflect.Constructor innerConstructor = Class.forName("main.PublicMorozov$Inner").getDeclaredConstructor(Class.forName("main.PublicMorozov"));
    innerConstructor.setAccessible(true);

    // заменяем таки содержимое нужного поля
    targetAsField.set(null, new java.lang.ref.WeakReference<Inner>((Inner) innerConstructor.newInstance(INSTANCE)));
  }
}