Skip to content

Commit

Permalink
re-add AddOpens, i'm just not smart enough to make a better impl :/
Browse files Browse the repository at this point in the history
  • Loading branch information
tildejustin committed Jan 9, 2024
1 parent 61083bd commit 93b00b6
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package me.modmuss50.optifabric.mixin;

import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.*;

@Pseudo
@Mixin(targets = "net.optifine.util.NativeMemory")
public class NativeMemoryMixin {
@SuppressWarnings("UnresolvedMixinReference")
@ModifyArg(method = "<clinit>", at = @At(value = "INVOKE", target = "Lnet/optifine/util/NativeMemory;makeLongSupplier([[Ljava/lang/String;)Ljava/util/function/LongSupplier;", ordinal = 0))
private static String[][] addNewSharedSecretsLocation(String[][] paths) {
return new String[][]{paths[0], paths[1], {"jdk.internal.access.SharedSecrets", "getJavaNioAccess", "getDirectBufferPool", "getMemoryUsed"}};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

// suppresses some warnings in the log
@Pseudo
@Mixin(targets = "ReflectorClass")
@Mixin(targets = "net.optifine.reflect.ReflectorClass")
public class ReflectorClassMixin {
@Shadow
private String targetClassName;
Expand All @@ -17,11 +17,11 @@ public class ReflectorClassMixin {
@SuppressWarnings("UnresolvedMixinReference")
@Inject(method = "getTargetClass", at = @At("HEAD"), remap = false)
private void getTargetClass(CallbackInfoReturnable<Class<?>> infoReturnable) {
if (!checked) { // only check the target if it hasn't been done yet
String name = targetClassName.replaceAll("/", ".");
if (!this.checked) { // only check the target if it hasn't been done yet
String name = this.targetClassName.replaceAll("/", ".");
if (name.startsWith("net.minecraft.launchwrapper") || name.startsWith("net.minecraftforge") || "optifine.OptiFineClassTransformer".equals(name)) {
checked = true;
this.checked = true;
}
}
}
}
}
1 change: 1 addition & 0 deletions 1.13.2/src/main/resources/optifabric.optifine.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"package": "me.modmuss50.optifabric.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"NativeMemoryMixin",
"PatcherMixin",
"ReflectorClassMixin"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import com.chocohead.mm.api.ClassTinkerers;
import me.modmuss50.optifabric.Pair;
import me.modmuss50.optifabric.patcher.ClassCache;
import me.modmuss50.optifabric.patcher.*;
import net.fabricmc.loader.api.*;
import org.spongepowered.asm.mixin.Mixins;
import org.spongepowered.asm.service.*;
import org.spongepowered.asm.util.JavaVersion;

import java.io.*;
import java.nio.file.Path;
Expand All @@ -24,6 +25,11 @@ public void run() {
if (!this.validateMods()) {
return;
}
if (JavaVersion.current() >= JavaVersion.JAVA_9) {
AddOpens.open("java.base", "jdk.internal.misc");
AddOpens.open("java.base", "jdk.internal.access");
AddOpens.open("java.base", "java.nio");
}
try {
Pair<Path, ClassCache> runtime = new OptifineSetup().getRuntime();

Expand Down
127 changes: 127 additions & 0 deletions src/main/java/me/modmuss50/optifabric/patcher/AddOpens.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright 2021 Stefan Zobel
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.modmuss50.optifabric.patcher;

import java.lang.reflect.*;
import java.util.Optional;

/**
* A utility class that allows to open arbitrary packages to the calling module
* at runtime, so it is a kind of dynamic device for "--add-opens" that could be
* used inside libraries instead of forcing the application to be run with
* command line parameters like "--add-opens java.base/java.util=ALL-UNNAMED" or
* having the "Add-Opens:" entries supplied in the application Jar manifest.
* Note that this still works in the Java 17 GA release, dated 2021-09-14 but it
* may break at any time in the future (theoretically even for a minor
* release!).
*/
public final class AddOpens {
// field offset of the override field (Warning: this may change at any time!)
private static final long OVERRIDE_OFFSET = 12;
private static final Object U = getUnsafe();

private AddOpens() {
throw new AssertionError();
}

/**
* Open one or more packages in the given module to the current module. Example
* usage:
*
* <pre>{@code
* boolean success = AddOpens.open("java.base", "java.util", "java.net");
* }</pre>
*
* @param moduleName the module you want to open
* @param packageNames packages in that module you want to be opened
* @return {@code true} if the open operation has succeeded for all packages,
* otherwise {@code false}
*/
public static boolean open(String moduleName, String... packageNames) {
// Use reflection so that this code can run on Java 8
Class<?> javaLangModule;
try {
javaLangModule = Class.forName("java.lang.Module");
} catch (Throwable t) {
// we must be on Java 8
return true;
}
try {
// the module we are currently running in (either named or unnamed)
Object thisModule = getCurrentModule();
// find the module to open
Object targetModule = findModule(moduleName);
// get the method that is also used by "--add-opens"
Method m = javaLangModule.getDeclaredMethod("implAddOpens", String.class, javaLangModule);
// override language-level access checks
setAccessible(m);
// open given packages in the target module to this module
for (String package_ : packageNames) {
m.invoke(targetModule, package_, thisModule);
}
return true;
} catch (Throwable ignore) {
return false;
}
}

private static Object findModule(String moduleName) {
// Use reflection so that this code can run on Java 8
try {
Class<?> moduleLayerClass = Class.forName("java.lang.ModuleLayer");
Method bootMethod = moduleLayerClass.getDeclaredMethod("boot");
Object bootLayer = bootMethod.invoke(null);
Method findModuleMethod = moduleLayerClass.getDeclaredMethod("findModule", String.class);
Optional<?> module = (Optional<?>) findModuleMethod.invoke(bootLayer, moduleName);
return module.get();
} catch (Throwable t) {
return null;
}
}

private static Object getCurrentModule() {
// use reflection so that this code can run on Java 8
try {
Method m = Class.class.getDeclaredMethod("getModule");
setAccessible(m);
return m.invoke(AddOpens.class);
} catch (Throwable t) {
return null;
}
}

private static void setAccessible(Method method) {
if (U != null) {
try {
U.getClass().getMethod("putBoolean", Object.class, long.class, boolean.class).invoke(U, method, OVERRIDE_OFFSET, true);
} catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

private static Object getUnsafe() {
try {
Class<?> sunMiscUnsafe = Class.forName("sun.misc.Unsafe");
Field unsafe = sunMiscUnsafe.getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
return unsafe.get(null);
} catch (Throwable ignore) {
return null;
}
}
}

0 comments on commit 93b00b6

Please sign in to comment.