JVM - 取消字段final/修改final字段

class Main {
    private const val METHOD_MH_ACCESSOR = 0x1
    private var UNSAFE: Unsafe? = null

	init {
 		var unsafe: Unsafe? = null
        try {
            val f = Unsafe::class.java.getDeclaredField("theUnsafe")
            f.isAccessible = true
            unsafe = f[null] as Unsafe
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        UNSAFE = unsafe

        if (getJVMVersion() == 18) {
            // workaround https://openjdk.java.net/jeps/416 - JEP 416: Reimplement Core Reflection with Method Handles
            try {
                val reflectionFactoryClass = Class.forName("jdk.internal.reflect.ReflectionFactory")
                val useDirectMethodHandle = reflectionFactoryClass.getDeclaredField("useDirectMethodHandle")
                val useDirectMethodHandleOffset = UNSAFE!!.staticFieldOffset(useDirectMethodHandle)
                UNSAFE!!.putInt(reflectionFactoryClass, useDirectMethodHandleOffset, METHOD_MH_ACCESSOR)
            } catch (e: Throwable) {
                e.printStackTrace()
            }
        } else if (getJVMVersion() >= 19) {
            // todo: code below seems useless
            try {
                val reflectionFactoryClass = Class.forName("jdk.internal.reflect.ReflectionFactory")
                val configField = reflectionFactoryClass.getDeclaredField("config")
                val configOffset = UNSAFE!!.staticFieldOffset(configField)

                UNSAFE!!.putObject(reflectionFactoryClass, configOffset, null)
                System.setProperty("jdk.reflect.useDirectMethodHandle", "false")
            } catch (e: Throwable) {
                e.printStackTrace()
            }
        }
	}

	 fun unloadFinalModifier(field: Field) {
        getAllFieldsUnsafely(Field::class.java)
            .firstOrNull {
                it.name == "modifiers"
                    && it.type == Integer.TYPE
            }?.let {
                setAccessible(it)
                it.setInt(field, it.getInt(field) and Modifier.FINAL.inv())
            }
    }
}