Skip to content

Commit

Permalink
Merge branch 'main' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
wagyourtail committed Jul 31, 2024
2 parents d58675d + 60b7456 commit 6b89a42
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 2 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ shadeDowngradedApi {
The tasks have all the same flags as the extension, so you can change them separately,
their default value is to use the global one from the extension.

If you are merging multiple downgraded jars, please merge from the downgradeJar tasks, and then shade on the resulting mono-jar.
otherwise some API stubs may be missing, due to how shade only includes what is used.

Optionally, you can also depend on the shadeDowngradedApi task when running build.

```gradle
Expand Down
1 change: 1 addition & 0 deletions docs/Bytecode Manipulation.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Stubs have several other fields that change their behavior:
mostly for things like reflection and runtime class definition.
* `noSpecial` indicates that the stub should not be used for `INVOKESPECIAL` calls.
* `downgradeVersion` adds an extra argument to the stub for the original version of the class, this is useful for multi-version stubs, such as reflection.
* `excludeChild` prevent a stub from being applied to a child-class of the target. for example, `String#isEmpty` is since java 6, but `CharSequence#isEmpty` is since java 15.

### Modify

Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,60 @@
package xyz.wagyourtail.jvmdg.j9.stub.java_base;


import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import xyz.wagyourtail.jvmdg.version.Modify;
import xyz.wagyourtail.jvmdg.version.Ref;
import xyz.wagyourtail.jvmdg.version.Stub;

import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;

public class J_L_ClassLoader {
private static final Map<ClassLoader, String> nameMap = Collections.synchronizedMap(new WeakHashMap<>());

@Modify(ref = @Ref(value = "Ljava/lang/ClassLoader;", member = "<init>", desc = "(Ljava/lang/String;Ljava/lang/ClassLoader;)V"))
public static void init(MethodNode mnode, int i) {
MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i);
InsnList list = new InsnList();
// stack: ClassLoader (U), String, ClassLoader
list.add(new InsnNode(Opcodes.SWAP));
// stack: ClassLoader (U), ClassLoader, String
list.add(new InsnNode(Opcodes.DUP_X2));
// stack: String, ClassLoader (U), ClassLoader, String
list.add(new InsnNode(Opcodes.POP));
// stack: String, ClassLoader (U), ClassLoader
list.add(new InsnNode(Opcodes.DUP2));
// stack: String, ClassLoader (U), ClassLoader, ClassLoader (U), ClassLoader
// init
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/ClassLoader", "<init>", "(Ljava/lang/ClassLoader;)V", false));
// stack: String, ClassLoader, ClassLoader
list.add(new InsnNode(Opcodes.POP));
// stack: String, ClassLoader
// call setName
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false));
// stack:

// TODO: stub init's...
mnode.instructions.insert(node, list);
mnode.instructions.remove(node);
}

public static void setClassloaderName(String name, ClassLoader classLoader) {
if (name != null && name.isEmpty()) {
throw new IllegalArgumentException("name must be non-empty or null");
}
nameMap.put(classLoader, name);
}

@Stub
public static String getName(ClassLoader classLoader) {
// TODO: check if subclass actually overrides this method
return null;
return nameMap.get(classLoader);
}

@Stub
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package xyz.wagyourtail.jvmdg.j9.stub.java_base;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import xyz.wagyourtail.jvmdg.version.Modify;
import xyz.wagyourtail.jvmdg.version.Ref;

public class J_N_URLClassLoader {

@Modify(ref = @Ref(value = "java/net/URLClassLoader", member = "<init>", desc = "(Ljava/lang/String;[Ljava/net/URL;Ljava/lang/ClassLoader;)V"))
public static void init1(MethodNode mnode, int i) {
MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i);
InsnList list = new InsnList();
// stack: URLClassLoader (U), String, URL[], ClassLoader
list.add(new InsnNode(Opcodes.DUP2_X1));
// stack: URLClassLoader (U), URL[], ClassLoader, String, URL[], ClassLoader
list.add(new InsnNode(Opcodes.POP2));
// stack: URLClassLoader (U), URL[], ClassLoader, String
list.add(new InsnNode(Opcodes.DUP2_X2));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, String
list.add(new InsnNode(Opcodes.POP));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader
list.add(new InsnNode(Opcodes.DUP2_X1));
// stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U), URL[], ClassLoader
list.add(new InsnNode(Opcodes.POP2));
// stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.DUP_X2));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.DUP_X2));
// stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.POP));
// stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader
// init
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/net/URLClassLoader", "<init>", "([Ljava/net/URL;Ljava/lang/ClassLoader;)V", false));
// stack: ClassLoader, String, URLClassLoader
// call setName
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false));
// stack: ClassLoader
list.add(new InsnNode(Opcodes.POP));
// stack:

mnode.instructions.insert(node, list);
mnode.instructions.remove(node);
}

@Modify(ref = @Ref(value = "java/net/URLClassLoader", member = "<init>", desc = "(Ljava/lang/String;[Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/net/URLStreamHandlerFactory;)V"))
public static void init2(MethodNode mnode, int i) {
MethodInsnNode node = (MethodInsnNode) mnode.instructions.get(i);
InsnList list = new InsnList();
// stack: URLClassLoader (U), String, URL[], ClassLoader, URLStreamHandlerFactory

int var = mnode.maxLocals++;
list.add(new VarInsnNode(Opcodes.ASTORE, var));

// stack: URLClassLoader (U), String, URL[], ClassLoader
list.add(new InsnNode(Opcodes.DUP2_X1));
// stack: URLClassLoader (U), URL[], ClassLoader, String, URL[], ClassLoader
list.add(new InsnNode(Opcodes.POP2));
// stack: URLClassLoader (U), URL[], ClassLoader, String
list.add(new InsnNode(Opcodes.DUP2_X2));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, String
list.add(new InsnNode(Opcodes.POP));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader
list.add(new InsnNode(Opcodes.DUP2_X1));
// stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U), URL[], ClassLoader
list.add(new InsnNode(Opcodes.POP2));
// stack: ClassLoader, String, URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.DUP_X2));
// stack: ClassLoader, String, URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.DUP_X2));
// stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLClassLoader (U)
list.add(new InsnNode(Opcodes.POP));
// stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader
list.add(new VarInsnNode(Opcodes.ALOAD, var));
// stack: ClassLoader, String, URLClassLoader (U), URLClassLoader (U), URL[], ClassLoader, URLStreamHandlerFactory
// init
list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/net/URLClassLoader", "<init>", "([Ljava/net/URL;Ljava/lang/ClassLoader;Ljava/net/URLStreamHandlerFactory;)V", false));
// stack: ClassLoader, String, URLClassLoader
// call setName
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getInternalName(J_L_ClassLoader.class), "setClassloaderName", "(Ljava/lang/String;Ljava/lang/ClassLoader;)V", false));
// stack: ClassLoader
list.add(new InsnNode(Opcodes.POP));
// stack:

mnode.instructions.insert(node, list);
mnode.instructions.remove(node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public void init() {
// URLStreamHandlerProvider
stub(J_N_Buffer.class);
stub(J_N_F_Path.class);
stub(J_N_URLClassLoader.class);
// AuthProvider
// DrbgParameters
// KeyStore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package xyz.wagyourtail.downgradetest;

import java.net.URLClassLoader;

public class TestClassloader {

public static void main(String[] args) {
URLClassLoader cl = new URLClassLoader("name1", new java.net.URL[0], TestClassloader.class.getClassLoader());
System.out.println(cl.getName());

URLClassLoader cl2 = new URLClassLoader("name2", new java.net.URL[0], TestClassloader.class.getClassLoader(), null);
System.out.println(cl2.getName());

CLExt cl3 = new CLExt(TestClassloader.class.getClassLoader());
System.out.println(cl3.getName());

}

private static class CLExt extends ClassLoader {

public CLExt(ClassLoader parent) {
super("name3", parent);
}

}

}

0 comments on commit 6b89a42

Please sign in to comment.