幸いなことに、このプログラムを使用すると、外出先で任意のコードを含むモジュールを接続できます。 だから-私たちの処分ですべての反射の力!
これは概念実証であるため、特定のタスクでは、少なくともアクセサーの目的のタイプを設定する必要があります。一般的に、コンテキストからコードを引き裂くと、一部のブロックが意味を失う可能性があります。 たとえば、上記の例では、一般にアクセサーを交換しなくてもすべてが機能しますが、finalを削除するだけで十分です。 これはオブジェクトに対してのみ機能することが保証されることに注意してください。 通常、プリミティブはコンパイラーによってインライン化されます。
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)));
}
}
* This source code was highlighted with Source Code Highlighter .