本篇教程由作者设定未经允许禁止转载。
首先,在正式开始教程前,我们要先明白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);}
}
以上就是该教程的全部内容,如果有错误或可以改进的地方,欢迎指出。


