本篇教程由作者设定未经允许禁止转载。

首先,在正式开始教程前,我们要先明白unsafe的作用

sun.misc.Unsafe 是 Java 中的一个内部类,它提供了一系列低级、不安全操作的方法,允许开发者直接操作内存、绕过 Java 的安全检查机制。主要功能包括:

直接内存操作 - 分配、释放、读写内存

字段偏移量获取 - 获取对象字段在内存中的精确位置

绕过访问限制 - 修改 final 字段、访问私有字段

对象实例化 - 不调用构造函数创建对象实例

线程操作 - 线程挂起和恢复

CAS 操作 - 原子性的比较并交换

警告:Unsafe 操作非常危险,可能破坏 JVM 稳定性,仅推荐在了解风险的高级场景中使用。

以下是获取unsafe的代码,笔者已经将该方法封装成了一个函数,在需要时可以直接调用

function getUnsafe() {
  try{
    // 加载 sun.misc.Unsafe 类,因为无法通过kubeJS的Javaloadclass直接加载这个类,所以使用Java.class.forName
    let unsafeClass = Java.class.forName("sun.misc.Unsafe");
    // 获取 Unsafe 类中的 theUnsafe 字段(这是单例实例)
    let theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
    // 设置字段可访问,绕过 Java 的访问控制
    theUnsafeField.setAccessible(true);
    // 获取 theUnsafe 字段的值(由于是静态字段,传入 null)
    let unsafe = theUnsafeField.get(null);
    return unsafe;
  } catch (e) {
    console.log(e)
  }
}


以下是使用unsafe的示例


往内存中写入

getUnsafe().putAddress(0,0)

上面的代码会导致崩溃,因为这行代码试图在内存地址 0 处写入值 0,这直接触发了操作系统的内存保护机制。


修改字段值

当我们进入存档时,这时候注册表已经被冻结,无法对注册表进行再修改,但是使用unsafe,我们可以直接修改冻结的字段值,以达到解除注册表冻结的效果,以下代码用于解除维度类型注册表的冻结

注意:未经测试,不保证可用

function unfreezeRegistry() {
    try {
        let MappedRegistry = Java.loadClass("net.minecraft.core.MappedRegistry");
        let Registries = Java.loadClass("net.minecraft.core.registries.Registries");
        let Registry = Java.loadClass("net.minecraft.core.Registry");
        let DimensionType = Java.loadClass("net.minecraft.world.level.dimension.DimensionType");
        let unsafe = getUnsafe();
        if (!unsafe) return;
        let registryAccess = Utils.server.registryAccess();
        let dimensionTypeRegistry = registryAccess.registryOrThrow(Registries.DIMENSION_TYPE);
        let mappedRegistry = dimensionTypeRegistry;
            try {
                frozenField = MappedRegistry.class.getDeclaredField("f_205845_");
                console.log("找到字段: " + fieldName);
            } catch (e) {
                console.log(e)
            }
        if (!frozenField) {
            console.log("无法找到 frozen 字段");
        }
        frozenField.setAccessible(true);
        let frozenOffset = unsafe.objectFieldOffset(frozenField);
        // 获取当前值
        let currentValue = unsafe.getBooleanVolatile(mappedRegistry, frozenOffset);
        console.log("当前 frozen 状态: " + currentValue);
        // 修改为 false
        unsafe.putBooleanVolatile(mappedRegistry, frozenOffset, false);
        // 验证修改
        let newValue = unsafe.getBooleanVolatile(mappedRegistry, frozenOffset);
        console.log("维度类型注册表解冻成功");
    } catch (e) {
        console.log("维度类型解冻注册表失败: " + e);
    }
}


以上就是该教程的全部内容,如果有错误或可以改进的地方,欢迎指出。