diff --git a/build.gradle.kts b/build.gradle.kts index 29bbc622..80af70d9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -104,12 +104,14 @@ tasks.compileTestJava { } tasks.test { + outputs.upToDateWhen { false } useJUnitPlatform() + dependsOn( project(":downgradetest").tasks.build, project(":java-api").tasks.build ) - jvmArgs("-Djvmdg.debug=true") +// jvmArgs("-Djvmdg.debug=true") javaLauncher = javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(testVersion.toInt())) } diff --git a/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_I_PrintWriter.java b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_I_PrintWriter.java index a9b472a4..27d7bd06 100644 --- a/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_I_PrintWriter.java +++ b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_I_PrintWriter.java @@ -1,20 +1,52 @@ package xyz.wagyourtail.jvmdg.j10.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; -import xyz.wagyourtail.jvmdg.version.Stub; - -import java.io.BufferedWriter; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.nio.charset.Charset; public class J_I_PrintWriter { - @Stub(ref = @Ref(value = "Ljava/io/PrintWriter;", member = "")) - public static PrintWriter init(OutputStream out, boolean autoFlush, Charset encoding) { - return new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, encoding)), autoFlush); + @Modify(ref = @Ref(value = "Ljava/io/PrintWriter;", member = "", desc = "(Ljava/io/OutputStream;ZLjava/nio/charset/Charset;)V")) + public static void init(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: PrintWriter, OutputStream, boolean, Charset + list.add(new InsnNode(Opcodes.DUP2_X1)); + // stack: PrintWriter, boolean, Charset, OutputStream, boolean, Charset + list.add(new InsnNode(Opcodes.SWAP)); + // stack: PrintWriter, boolean, Charset, OutputStream, Charset, boolean + list.add(new InsnNode(Opcodes.POP)); + // stack: PrintWriter, boolean, Charset, OutputStream, Charset + list.add(new TypeInsnNode(Opcodes.NEW, "java/io/OutputStreamWriter")); + // stack: PrintWriter, boolean, Charset, OutputStream, Charset, (U) OutputStreamWriter + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: PrintWriter, boolean, Charset, (U) OutputStreamWriter, OutputStream, Charset, (U) OutputStreamWriter + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: PrintWriter, boolean, Charset, (U) OutputStreamWriter, (U) OutputStreamWriter, OutputStream, Charset, (U) OutputStreamWriter + list.add(new InsnNode(Opcodes.POP)); + // stack: PrintWriter, boolean, Charset, (U) OutputStreamWriter, (U) OutputStreamWriter, OutputStream, Charset + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/io/OutputStreamWriter", "", "(Ljava/io/OutputStream;Ljava/nio/charset/Charset;)V", false)); + // stack: PrintWriter, boolean, Charset, OutputStreamWriter + list.add(new InsnNode(Opcodes.SWAP)); + // stack: PrintWriter, boolean, OutputStreamWriter, Charset + list.add(new InsnNode(Opcodes.POP)); + // stack: PrintWriter, boolean, OutputStreamWriter + list.add(new TypeInsnNode(Opcodes.NEW, "java/io/BufferedWriter")); + // stack: PrintWriter, boolean, OutputStreamWriter, (U) BufferedWriter + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: PrintWriter, boolean, (U) BufferedWriter, OutputStreamWriter, (U) BufferedWriter + list.add(new InsnNode(Opcodes.SWAP)); + // stack: PrintWriter, boolean, (U) BufferedWriter, (U) BufferedWriter, OutputStreamWriter + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/io/BufferedWriter", "", "(Ljava/io/Writer;)V", false)); + // stack: PrintWriter, boolean, BufferedWriter + list.add(new InsnNode(Opcodes.SWAP)); + // stack: PrintWriter, BufferedWriter, boolean + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/io/PrintWriter", "", "(Ljava/io/Writer;Z)V", false)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } } diff --git a/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_N_C_Channels.java b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_N_C_Channels.java new file mode 100644 index 00000000..0fb9d91b --- /dev/null +++ b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_N_C_Channels.java @@ -0,0 +1,28 @@ +package xyz.wagyourtail.jvmdg.j10.stub.java_base; + +import xyz.wagyourtail.jvmdg.version.Ref; +import xyz.wagyourtail.jvmdg.version.Stub; + +import java.io.Reader; +import java.io.Writer; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.channels.WritableByteChannel; +import java.nio.charset.Charset; +import java.util.Objects; + +public class J_N_C_Channels { + + @Stub(ref = @Ref("java/nio/channels/Channels")) + public static Reader newReader(ReadableByteChannel channel, Charset charset) { + Objects.requireNonNull(charset, "charset"); + return Channels.newReader(channel, charset.newDecoder(), -1); + } + + @Stub(ref = @Ref("java/nio/channels/Channels")) + public static Writer newWriter(WritableByteChannel channel, Charset charset) { + Objects.requireNonNull(charset, "charset"); + return Channels.newWriter(channel, charset.newEncoder(), -1); + } + +} diff --git a/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_U_Scanner.java b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_U_Scanner.java index ae8c6bd9..f4cb9f05 100644 --- a/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_U_Scanner.java +++ b/java-api/src/java10/java/xyz/wagyourtail/jvmdg/j10/stub/java_base/J_U_Scanner.java @@ -1,6 +1,10 @@ package xyz.wagyourtail.jvmdg.j10.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; @@ -10,9 +14,23 @@ public class J_U_Scanner { - @Stub(ref = @Ref(value = "Ljava/util/Scanner;", member = "")) - public static Scanner init(ReadableByteChannel source, Charset charset) { - return new Scanner(source, charset.name()); +// @Stub(ref = @Ref(value = "Ljava/util/Scanner;", member = "")) +// public static Scanner init(ReadableByteChannel source, Charset charset) { +// return new Scanner(source, charset.name()); +// } + + @Modify(ref = @Ref(value = "Ljava/util/Scanner;", member = "", desc = "(Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/Charset;)V")) + public static void init(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: Scanner, ReadableByteChannel, Charset + // call:J_N_C_Channels.newReader(ReadableByteChannel, Charset) + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, Type.getType(J_N_C_Channels.class).getInternalName(), "newReader", "(Ljava/nio/channels/ReadableByteChannel;Ljava/nio/charset/Charset;)Ljava/io/Reader;", false)); + // stack: Scanner, Reader + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/Scanner", "", "(Ljava/lang/Readable;)V", false)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } } diff --git a/java-api/src/java15/java/xyz/wagyourtail/jvmdg/j15/stub/java_base/J_U_NoSuchElementException.java b/java-api/src/java15/java/xyz/wagyourtail/jvmdg/j15/stub/java_base/J_U_NoSuchElementException.java index 827a46b7..3e07fc2e 100644 --- a/java-api/src/java15/java/xyz/wagyourtail/jvmdg/j15/stub/java_base/J_U_NoSuchElementException.java +++ b/java-api/src/java15/java/xyz/wagyourtail/jvmdg/j15/stub/java_base/J_U_NoSuchElementException.java @@ -1,6 +1,9 @@ package xyz.wagyourtail.jvmdg.j15.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; @@ -8,18 +11,52 @@ public class J_U_NoSuchElementException { - @Stub(ref = @Ref(value = "Ljava/util/NoSuchElementException;", member = "")) - public static NoSuchElementException create(String s, Throwable cause) throws NoSuchMethodException { - var nse = new NoSuchElementException(s); - nse.initCause(cause); - return nse; + @Modify(ref = @Ref(value = "Ljava/util/NoSuchElementException;", member = "", desc = "(Ljava/lang/String;Ljava/lang/Throwable;)V")) + public static void init(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + // stack: NoSuchElementException, String, Throwable + list.add(new InsnNode(Opcodes.DUP_X2)); + // stack: Throwable, NoSuchElementException, String, Throwable + list.add(new InsnNode(Opcodes.POP)); + // stack: Throwable, NoSuchElementException, String + list.add(new InsnNode(Opcodes.DUP2)); + // stack: Throwable, NoSuchElementException, String, NoSuchElementException, String + // call init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/NoSuchElementException", "", "(Ljava/lang/String;)V", false)); + // stack: Throwable, NoSuchElementException, String + list.add(new InsnNode(Opcodes.POP)); + // stack: Throwable, NoSuchElementException + list.add(new InsnNode(Opcodes.SWAP)); + // stack: NoSuchElementException, Throwable + // call initCause + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/NoSuchElementException", "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", false)); + // stack: NoSuchElementException + list.add(new InsnNode(Opcodes.POP)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } - @Stub(ref = @Ref(value = "Ljava/util/NoSuchElementException;", member = "")) - public static NoSuchElementException create(Throwable cause) throws NoSuchMethodException { - var nse = new NoSuchElementException(cause == null ? null : cause.toString()); - nse.initCause(cause); - return nse; + @Modify(ref = @Ref(value = "java/util/NoSuchElementException", member = "", desc = "(Ljava/lang/Throwable;)V")) + public static void init2(MethodNode mNode, int i) { + AbstractInsnNode node = mNode.instructions.get(i); + InsnList list = new InsnList(); + // stack: NoSuchElementException, Throwable + list.add(new InsnNode(Opcodes.DUP2)); + // stack: NoSuchElementException, Throwable, NoSuchElementException, Throwable + list.add(new InsnNode(Opcodes.POP)); + // stack: NoSuchElementException, Throwable, NoSuchElementException + // call init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/util/NoSuchElementException", "", "()V", false)); + // stack: NoSuchElementException, Throwable + // call initCause + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/util/NoSuchElementException", "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;", false)); + // stack: NoSuchElementException + list.add(new InsnNode(Opcodes.POP)); + + mNode.instructions.insert(node, list); + mNode.instructions.remove(node); } } diff --git a/java-api/src/java16/java/xyz/wagyourtail/jvmdg/j16/stub/java_base/J_L_IndexOutOfBoundsException.java b/java-api/src/java16/java/xyz/wagyourtail/jvmdg/j16/stub/java_base/J_L_IndexOutOfBoundsException.java index c6bdf618..1187d027 100644 --- a/java-api/src/java16/java/xyz/wagyourtail/jvmdg/j16/stub/java_base/J_L_IndexOutOfBoundsException.java +++ b/java-api/src/java16/java/xyz/wagyourtail/jvmdg/j16/stub/java_base/J_L_IndexOutOfBoundsException.java @@ -1,13 +1,36 @@ package xyz.wagyourtail.jvmdg.j16.stub.java_base; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; public class J_L_IndexOutOfBoundsException { - @Stub(ref = @Ref(value = "java/lang/IndexOutOfBoundsException", member = "")) - public static IndexOutOfBoundsException init(long i) { - return new IndexOutOfBoundsException("Index out of range: " + i); + + @Modify(ref = @Ref(value = "java/lang/IndexOutOfBoundsException", member = "", desc = "(J)V")) + public static void init(MethodNode mNode, int i) { + AbstractInsnNode node = mNode.instructions.get(i); + InsnList list = new InsnList(); + // string concat factory, "Index out of range: \u0001" + list.add(new InvokeDynamicInsnNode( + "makeConcatWithConstants", + "(J)Ljava/lang/String;", + new Handle( + Opcodes.H_INVOKESTATIC, + "java/lang/invoke/StringConcatFactory", + "makeConcatWithConstants", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;" + ), + "Index out of range: \u0001" + )); + // call init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/IndexOutOfBoundsException", "", "(Ljava/lang/String;)V", false)); + + mNode.instructions.insert(node, list); + mNode.instructions.remove(node); } } diff --git a/java-api/src/java17/java/xyz/wagyourtail/jvmdg/j17/stub/java_base/J_U_SplittableRandom.java b/java-api/src/java17/java/xyz/wagyourtail/jvmdg/j17/stub/java_base/J_U_SplittableRandom.java index de38d4fb..606c1540 100644 --- a/java-api/src/java17/java/xyz/wagyourtail/jvmdg/j17/stub/java_base/J_U_SplittableRandom.java +++ b/java-api/src/java17/java/xyz/wagyourtail/jvmdg/j17/stub/java_base/J_U_SplittableRandom.java @@ -39,13 +39,13 @@ public static Stream splits(Splittabl } @Stub - public Stream rngs() { - return new SplittableRandomGeneratorImpl(new SplittableRandom()).rngs(); + public Stream rngs(SplittableRandom random) { + return new SplittableRandomGeneratorImpl(random).rngs(); } @Stub - public Stream rngs(long size) { - return new SplittableRandomGeneratorImpl(new SplittableRandom()).rngs(size); + public Stream rngs(SplittableRandom random, long size) { + return new SplittableRandomGeneratorImpl(random).rngs(size); } @Stub diff --git a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_IndexOutOfBoundsException.java b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_IndexOutOfBoundsException.java index 86c29bf3..b8a40525 100644 --- a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_IndexOutOfBoundsException.java +++ b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_L_IndexOutOfBoundsException.java @@ -1,14 +1,37 @@ package xyz.wagyourtail.jvmdg.j9.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; public class J_L_IndexOutOfBoundsException { - @Stub(ref = @Ref(value = "Ljava/lang/IndexOutOfBoundsException;", member = "")) - public static IndexOutOfBoundsException init(int index) { - return new IndexOutOfBoundsException("Index out of range: " + index); + @Modify(ref = @Ref(value = "java/lang/IndexOutOfBoundsException", member = "", desc = "(I)V")) + public static void init(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + + // stack: IndexOutOfBoundsException, int + // new StringBuilder("Index out of range: ").append(index) + list.add(new TypeInsnNode(Opcodes.NEW, "java/lang/StringBuilder")); + list.add(new InsnNode(Opcodes.DUP)); + list.add(new LdcInsnNode("Index out of range: ")); + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false)); + // stack: IndexOutOfBoundsException, int, StringBuilder + list.add(new InsnNode(Opcodes.SWAP)); + // stack: IndexOutOfBoundsException, StringBuilder, int + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append", "(I)Ljava/lang/StringBuilder;", false)); + // stack: IndexOutOfBoundsException, StringBuilder + list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false)); + // stack: IndexOutOfBoundsException, String + // call init + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/lang/IndexOutOfBoundsException", "", "(Ljava/lang/String;)V", false)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } } diff --git a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_M_BigInteger.java b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_M_BigInteger.java index d8e16873..6f2bd2e4 100644 --- a/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_M_BigInteger.java +++ b/java-api/src/java9/java/xyz/wagyourtail/jvmdg/j9/stub/java_base/J_M_BigInteger.java @@ -1,6 +1,9 @@ package xyz.wagyourtail.jvmdg.j9.stub.java_base; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.*; +import xyz.wagyourtail.jvmdg.version.Modify; import xyz.wagyourtail.jvmdg.version.Ref; import xyz.wagyourtail.jvmdg.version.Stub; @@ -15,14 +18,48 @@ public class J_M_BigInteger { public static final BigInteger TWO = BigInteger.valueOf(2); static final long LONG_MASK = 0xffffffffL; - @Stub(ref = @Ref(value = "Ljava/math/BigInteger;", member = "")) - public static BigInteger init(byte[] val, int off, int len) { - return new BigInteger(Arrays.copyOfRange(val, off, off + len)); + @Modify(ref = @Ref(value = "Ljava/math/BigInteger;", member = "", desc = "([BII)V")) + public static void init(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + + // stack: BigInteger, byte[], (start) int, (len) int + list.add(new InsnNode(Opcodes.DUP2)); + // stack: BigInteger, byte[], (start) int, (len) int, (start) int, (len) int + list.add(new InsnNode(Opcodes.IADD)); + // stack: BigInteger, byte[],(start) int, (len) int, (start+len) int + list.add(new InsnNode(Opcodes.SWAP)); + // stack: BigInteger, byte[], (start) int, (start+len) int, (len) int + list.add(new InsnNode(Opcodes.POP)); + // stack: BigInteger, byte[], (start) int, (start+len) int + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/Arrays", "copyOfRange", "([BII)[B", false)); + // stack: BigInteger, byte[] + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/math/BigInteger", "", "([B)V", false)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } - @Stub(ref = @Ref(value = "Ljava/math/BigInteger;", member = "")) - public static BigInteger init(int signum, byte[] magnitude, int off, int len) { - return new BigInteger(signum, Arrays.copyOfRange(magnitude, off, off + len)); + @Modify(ref = @Ref(value = "Ljava/math/BigInteger;", member = "", desc = "(I[BII)V")) + public static void init2(MethodNode mnode, int i) { + AbstractInsnNode node = mnode.instructions.get(i); + InsnList list = new InsnList(); + + // stack: BigInteger, int, byte[], (start) int, (len) int + list.add(new InsnNode(Opcodes.DUP2)); + // stack: BigInteger, int, byte[], (start) int, (len) int, (start) int, (len) int + list.add(new InsnNode(Opcodes.IADD)); + // stack: BigInteger, int, byte[], (start) int, (len) int, (start+len) int + list.add(new InsnNode(Opcodes.SWAP)); + // stack: BigInteger, int, byte[], (start) int, (start+len) int, (len) int + list.add(new InsnNode(Opcodes.POP)); + // stack: BigInteger, int, byte[], (start) int, (start+len) int + list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/Arrays", "copyOfRange", "([BII)[B", false)); + // stack: BigInteger, int, byte[] + list.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, "java/math/BigInteger", "", "(I[B)V", false)); + + mnode.instructions.insert(node, list); + mnode.instructions.remove(node); } @Stub diff --git a/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java10Downgrader.java b/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java10Downgrader.java index 1cd84469..dbc680de 100644 --- a/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java10Downgrader.java +++ b/java-api/src/main/java/xyz/wagyourtail/jvmdg/providers/Java10Downgrader.java @@ -17,6 +17,7 @@ public void init() { stub(J_L_Runtime$Version.class); // StackWalker stub(J_L_I_MethodType.class); + stub(J_N_C_Channels.class); stub(J_N_URLDecoder.class); stub(J_N_URLEncoder.class); // FileStore diff --git a/src/main/java/xyz/wagyourtail/jvmdg/ClassDowngrader.java b/src/main/java/xyz/wagyourtail/jvmdg/ClassDowngrader.java index e5ef3b34..4e132c30 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/ClassDowngrader.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/ClassDowngrader.java @@ -32,8 +32,6 @@ import java.util.concurrent.atomic.AtomicReference; public class ClassDowngrader { - public static final boolean QUIET = Boolean.getBoolean("jvmdg.quiet"); - public static final ClassDowngrader currentVersionDowngrader = new ClassDowngrader(Utils.getCurrentClassVersion()); // because parent is null, this is (essentially) a wrapper around the bootstrap classloader diff --git a/src/main/java/xyz/wagyourtail/jvmdg/Constants.java b/src/main/java/xyz/wagyourtail/jvmdg/Constants.java index 028ec183..f47db7f1 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/Constants.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/Constants.java @@ -7,6 +7,7 @@ public class Constants { public static final boolean DEBUG = Boolean.getBoolean("jvmdg.debug"); + public static final boolean QUIET = Boolean.getBoolean("jvmdg.quiet"); public static final File DIR = new File(".jvmdg"); public static final File DEBUG_DIR = new File(DIR, "debug"); diff --git a/src/main/java/xyz/wagyourtail/jvmdg/version/VersionProvider.java b/src/main/java/xyz/wagyourtail/jvmdg/version/VersionProvider.java index 67ca94f7..fb18b5c6 100644 --- a/src/main/java/xyz/wagyourtail/jvmdg/version/VersionProvider.java +++ b/src/main/java/xyz/wagyourtail/jvmdg/version/VersionProvider.java @@ -76,13 +76,14 @@ public static FullyQualifiedMemberNameAndDesc resolveStubTarget(Member member, R } Type desc; if (ref.desc().isEmpty()) { - if (name.equals("")) { - ret = Type.VOID_TYPE; - } desc = Type.getMethodType(ret, params.toArray(new Type[0])); } else { desc = Type.getMethodType(ref.desc()); } + if (name.equals("")) { + // due to not being able to pass UNINITIALIZED_THIS + throw new IllegalArgumentException(owner.getDescriptor() + ";" + desc + " shouldn't be @Stub, should be @Modify"); + } // re-assemble desc return new FullyQualifiedMemberNameAndDesc(owner, name, desc); } else if (member instanceof Field) { @@ -206,7 +207,7 @@ public List init() { try { List types = superTypeResolver.apply(type); if (types == null) { - if (!ClassDowngrader.QUIET) System.err.println(VersionProvider.this.getClass().getName() + " Could not find class " + type.getInternalName()); + if (!Constants.QUIET) System.err.println(VersionProvider.this.getClass().getName() + " Could not find class " + type.getInternalName()); types = Collections.emptyList(); } List superTypes = new ArrayList<>(); @@ -224,72 +225,89 @@ public List init() { } public void stub(Class clazz) { - if (clazz.isAnnotationPresent(Adapter.class)) { - Adapter stub = clazz.getAnnotation(Adapter.class); - if (stub.value().isEmpty()) { - throw new IllegalArgumentException("Class " + clazz.getName() + ", @Adapter must have a ref"); - } else { - Type value; - if (stub.value().startsWith("L") && stub.value().endsWith(";")) { - value = Type.getType(stub.value()); + try { + if (clazz.isAnnotationPresent(Adapter.class)) { + Adapter stub = clazz.getAnnotation(Adapter.class); + if (stub.value().isEmpty()) { + throw new IllegalArgumentException("Class " + clazz.getName() + ", @Adapter must have a ref"); } else { - value = Type.getObjectType(stub.value()); - } + Type value; + if (stub.value().startsWith("L") && stub.value().endsWith(";")) { + value = Type.getType(stub.value()); + } else { + value = Type.getObjectType(stub.value()); + } // if (classStubs.containsKey(type)) { // throw new IllegalArgumentException("Class " + clazz.getName() + ", @Adapter ref " + type.getInternalName() + " already exists"); // } - Type target; - if (stub.target().isEmpty()) { - target = Type.getType(clazz); - } else { - if (stub.target().startsWith("L") && stub.target().endsWith(";")) { - target = Type.getType(stub.target()); + Type target; + if (stub.target().isEmpty()) { + target = Type.getType(clazz); } else { - target = Type.getObjectType(stub.target()); + if (stub.target().startsWith("L") && stub.target().endsWith(";")) { + target = Type.getType(stub.target()); + } else { + target = Type.getObjectType(stub.target()); + } } + classStubs.put(value, new Pair, Adapter>>(target, new Pair, Adapter>(clazz, stub))); } - classStubs.put(value, new Pair, Adapter>>(target, new Pair, Adapter>(clazz, stub))); } - } - try { - for (Method method : clazz.getDeclaredMethods()) { - if (method.isAnnotationPresent(Stub.class)) { - Stub stub = method.getAnnotation(Stub.class); - FullyQualifiedMemberNameAndDesc target = resolveStubTarget(method, stub.ref()); - Type owner = target.getOwner(); - MemberNameAndDesc member = target.toMemberNameAndDesc(); - getStubMapper(owner).addStub(member, method, stub); - } else if (method.isAnnotationPresent(Modify.class)) { - Modify modify = method.getAnnotation(Modify.class); - FullyQualifiedMemberNameAndDesc target = resolveModifyTarget(method, modify.ref()); - Type owner = target.getOwner(); - MemberNameAndDesc member = target.toMemberNameAndDesc(); - // ensure method parameters are valid - Class[] params = method.getParameterTypes(); - for (int i = 0; i < params.length; i++) { - if (i >= Modify.MODIFY_SIG.length) { - throw new IllegalArgumentException("Class " + clazz.getName() + ", @Modify method " + method.getName() + " has too many parameters"); + try { + for (Method method : clazz.getDeclaredMethods()) { + try { + if (method.isAnnotationPresent(Stub.class)) { + Stub stub = method.getAnnotation(Stub.class); + FullyQualifiedMemberNameAndDesc target = resolveStubTarget(method, stub.ref()); + Type owner = target.getOwner(); + MemberNameAndDesc member = target.toMemberNameAndDesc(); + getStubMapper(owner).addStub(member, method, stub); + } else if (method.isAnnotationPresent(Modify.class)) { + Modify modify = method.getAnnotation(Modify.class); + FullyQualifiedMemberNameAndDesc target = resolveModifyTarget(method, modify.ref()); + Type owner = target.getOwner(); + MemberNameAndDesc member = target.toMemberNameAndDesc(); + // ensure method parameters are valid + Class[] params = method.getParameterTypes(); + for (int i = 0; i < params.length; i++) { + if (i >= Modify.MODIFY_SIG.length) { + throw new IllegalArgumentException("Class " + clazz.getName() + ", @Modify method " + method.getName() + " has too many parameters"); + } + if (params[i] != Modify.MODIFY_SIG[i]) { + throw new IllegalArgumentException("Class " + clazz.getName() + ", @Modify method " + method.getName() + " parameter " + i + " must be of type " + Modify.MODIFY_SIG[i].getName()); + } + } + getStubMapper(owner).addModify(member, method, modify); } - if (params[i] != Modify.MODIFY_SIG[i]) { - throw new IllegalArgumentException("Class " + clazz.getName() + ", @Modify method " + method.getName() + " parameter " + i + " must be of type " + Modify.MODIFY_SIG[i].getName()); + } catch (Throwable e) { + if (!Constants.QUIET) { + System.out.println("ERROR: failed to create stub for " + clazz.getName() + " (" + e.getMessage().split("\n")[0] + ")"); + e.printStackTrace(System.err); } } - getStubMapper(owner).addModify(member, method, modify); + } + } catch (Throwable e) { + if (!Constants.QUIET) { + System.out.println("ERROR: failed to resolve methods for " + clazz.getName()); + e.printStackTrace(System.err); } } - } catch (Throwable e) { -// throw new RuntimeException("failed to create stub " + clazz.getName(), e); -// System.out.println("ERROR: failed to create stub for " + clazz.getName() + " (" + e.getMessage().split("\n")[0] + ")"); -// e.printStackTrace(System.err); - } - try { - // inner classes - for (Class inner : clazz.getDeclaredClasses()) { - stub(inner); + try { + // inner classes + for (Class inner : clazz.getDeclaredClasses()) { + stub(inner); + } + } catch (Throwable e) { + if (!Constants.QUIET) { + System.out.println("ERROR: failed to resolve inner classes for " + clazz.getName()); + e.printStackTrace(System.err); + } } } catch (Throwable e) { -// throw new RuntimeException("failed to create stub for inner classes of " + clazz.getName(), e); -// System.out.println("ERROR: failed to create stub for inner classes of " + clazz.getName() + " (" + e.getMessage().split("\n")[0] + ")"); + if (!Constants.QUIET) { + System.out.println("ERROR: failed to create stub(s) for " + clazz.getName()); + e.printStackTrace(System.err); + } } }