JavaとPublic Morozovのパターン

実行中のプログラムで再定義する必要があると、プライベートファイナルとしてマークされたフィールド。 サーバーが原因でプログラムを停止することは不可能でした。 さて、小さな追加として、変数の型は内部クラスとして定義されました。 もちろん、プライベートでもあります。



幸いなことに、このプログラムを使用すると、外出先で任意のコードを含むモジュールを接続できます。 だから-私たちの処分ですべての反射の力!



これは概念実証であるため、特定のタスクでは、少なくともアクセサーの目的のタイプを設定する必要があります。一般的に、コンテキストからコードを引き裂くと、一部のブロックが意味を失う可能性があります。 たとえば、上記の例では、一般にアクセサーを交換しなくてもすべてが機能しますが、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 .







All Articles