Skip to content

Commit 36ce0c7

Browse files
committed
Fix BootstrapLauncher leaving dangling jars open in 1.20.1
1 parent 69019e4 commit 36ce0c7

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

build.gradle

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ shadowJar {
6767
// Workaround: double-nest the jar.
6868
from shadowBugWorkaround
6969
}
70-
assemble.dependsOn shadowJar
7170

7271
shadowJar {
7372
archiveClassifier.set('')
@@ -79,8 +78,22 @@ configurations {
7978
}
8079
}
8180

81+
tasks.register("packageJar", Copy) {
82+
from(tasks.named("shadowJar").get().archiveFile)
83+
rename { String fileName ->
84+
// a simple way is to remove the "-$version" from the jar filename
85+
// but you can customize the filename replacement rule as you wish.
86+
fileName.replace("-$project.version", "")
87+
}
88+
into("${rootProject.layout.buildDirectory.get()}/libs")
89+
}
90+
91+
assemble.dependsOn tasks.named("packageJar")
92+
8293
artifacts {
83-
productionAgent(shadowJar)
94+
productionAgent(rootProject.layout.buildDirectory.file("libs/blacksmith.jar")) {
95+
builtBy(tasks.named("packageJar"))
96+
}
8497
}
8598

8699
publishing {

main/src/main/java/org/embeddedt/blacksmith/impl/TransformerCore.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public class TransformerCore {
4242
TRANSFORMERS.add(new BackgroundScanHandlerTransformer());
4343
TRANSFORMERS.add(new TransformerDiscovererConstantsTransformer());
4444
TRANSFORMERS.add(new ModDirTransformerDiscovererTransformer());
45+
TRANSFORMERS.add(new BootstrapLauncherTransformer());
4546
}
4647

4748
public static void log(String s) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.embeddedt.blacksmith.impl.transformers;
2+
3+
import org.objectweb.asm.Opcodes;
4+
import org.objectweb.asm.tree.ClassNode;
5+
import org.objectweb.asm.tree.InsnList;
6+
import org.objectweb.asm.tree.MethodInsnNode;
7+
import org.objectweb.asm.tree.MethodNode;
8+
import org.objectweb.asm.tree.VarInsnNode;
9+
10+
import java.lang.instrument.IllegalClassFormatException;
11+
import java.util.Arrays;
12+
import java.util.List;
13+
import java.util.Optional;
14+
15+
public class BootstrapLauncherTransformer implements RuntimeTransformer {
16+
@Override
17+
public List<String> getTransformedClasses() {
18+
return Arrays.asList("cpw/mods/bootstraplauncher/BootstrapLauncher");
19+
}
20+
21+
@Override
22+
public void transformClass(ClassNode data) throws IllegalClassFormatException {
23+
for (MethodNode method : data.methods) {
24+
if (method.name.equals("main") && (method.access & Opcodes.ACC_STATIC) != 0) {
25+
Optional<MethodInsnNode> nameCaptureInLoop = RuntimeTransformer.streamInsnList(method.instructions)
26+
.filter(n -> n.getOpcode() == Opcodes.INVOKEINTERFACE)
27+
.map(MethodInsnNode.class::cast)
28+
.filter(m -> m.name.equals("name") && m.owner.equals("cpw/mods/jarhandling/SecureJar"))
29+
.findFirst();
30+
nameCaptureInLoop.ifPresent(methodInsnNode -> RuntimeTransformer.searchBackward(methodInsnNode, insn -> insn.getOpcode() == Opcodes.ALOAD).ifPresent(aLoad -> {
31+
RuntimeTransformer.searchForward(methodInsnNode, insn -> {
32+
if (insn.getOpcode() == Opcodes.INVOKEVIRTUAL) {
33+
MethodInsnNode node = (MethodInsnNode) insn;
34+
return node.owner.equals("java/util/ArrayList") && node.name.equals("add");
35+
} else {
36+
return false;
37+
}
38+
}).ifPresent(listAdd -> {
39+
InsnList epilogueClose = new InsnList();
40+
epilogueClose.add(new VarInsnNode(Opcodes.ALOAD, ((VarInsnNode) aLoad).var));
41+
epilogueClose.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "cpw/mods/jarhandling/SecureJar", "getRootPath", "()Ljava/nio/file/Path;", true));
42+
epilogueClose.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/nio/file/Path", "getFileSystem", "()Ljava/nio/file/FileSystem;", true));
43+
epilogueClose.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, "java/io/Closeable", "close", "()V", true));
44+
method.instructions.insert(listAdd, epilogueClose);
45+
});
46+
}));
47+
}
48+
}
49+
}
50+
}

main/src/main/java/org/embeddedt/blacksmith/impl/transformers/RuntimeTransformer.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
import java.lang.instrument.IllegalClassFormatException;
1313
import java.util.List;
14+
import java.util.Optional;
15+
import java.util.function.Function;
16+
import java.util.function.Predicate;
1417
import java.util.stream.Stream;
1518
import java.util.stream.StreamSupport;
1619

@@ -48,4 +51,23 @@ static int nextLocalVariableIndex(MethodNode method) {
4851
static Stream<AbstractInsnNode> streamInsnList(InsnList list) {
4952
return StreamSupport.stream(list.spliterator(), false);
5053
}
54+
55+
static Optional<AbstractInsnNode> search(AbstractInsnNode current, Function<AbstractInsnNode, AbstractInsnNode> advancer, Predicate<AbstractInsnNode> filter) {
56+
AbstractInsnNode next = advancer.apply(current);
57+
while (next != null) {
58+
if (filter.test(next)) {
59+
return Optional.of(next);
60+
}
61+
next = advancer.apply(next);
62+
}
63+
return Optional.empty();
64+
}
65+
66+
static Optional<AbstractInsnNode> searchForward(AbstractInsnNode current, Predicate<AbstractInsnNode> filter) {
67+
return search(current, AbstractInsnNode::getNext, filter);
68+
}
69+
70+
static Optional<AbstractInsnNode> searchBackward(AbstractInsnNode current, Predicate<AbstractInsnNode> filter) {
71+
return search(current, AbstractInsnNode::getPrevious, filter);
72+
}
5173
}

0 commit comments

Comments
 (0)