-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement jvm probing, refactor code accordingly
- Loading branch information
Showing
21 changed files
with
345 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
dcevm-detect/src/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/VMMeta.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection; | ||
|
||
import com.github.bsideup.jabel.Desugar; | ||
|
||
@Desugar | ||
public record VMMeta(boolean isDcevmPresent, String dcevmVersion) {} |
23 changes: 23 additions & 0 deletions
23
dcevm-detect/src/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/VMReport.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection; | ||
|
||
import com.github.bsideup.jabel.Desugar; | ||
import java.util.Optional; | ||
|
||
@Desugar | ||
public record VMReport(Optional<VMMeta> vmMeta, Optional<Exception> exception) { | ||
public static VMReport none() { | ||
return new VMReport(Optional.empty(), Optional.empty()); | ||
} | ||
|
||
public static VMReport none(String message) { | ||
return new VMReport(Optional.empty(), Optional.of(new Exception(message))); | ||
} | ||
|
||
public static VMReport exception(Exception exception) { | ||
return new VMReport(Optional.empty(), Optional.of(exception)); | ||
} | ||
|
||
public static VMReport of(VMMeta meta) { | ||
return new VMReport(Optional.of(meta), Optional.empty()); | ||
} | ||
} |
18 changes: 0 additions & 18 deletions
18
.../java/io/github/srdjanv/hotswapgradle/dcevmdetection/included/IncludedDcevmDetection.java
This file was deleted.
Oops, something went wrong.
35 changes: 35 additions & 0 deletions
35
...src/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/probe/PlatformJavaPaths.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection.probe; | ||
|
||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
public enum PlatformJavaPaths { | ||
MAC_OS("bin/java"), | ||
LINUX("bin/java"), | ||
WINDOWS("bin/java.exe"); | ||
|
||
public static Path resolveExecutable(Path javaHome) { | ||
if (Files.isRegularFile(javaHome)) throw new IllegalArgumentException("Java home is a file"); | ||
if (Files.isDirectory(javaHome.resolve("jre"))) javaHome = javaHome.resolve("jre"); | ||
return javaHome.resolve(get().path); | ||
} | ||
|
||
public static PlatformJavaPaths get() { | ||
String os = System.getProperty("os.name").toLowerCase(); | ||
|
||
if (os.contains("windows")) { | ||
return WINDOWS; | ||
} else if (os.contains("mac") || os.contains("darwin")) { | ||
return MAC_OS; | ||
} else if (os.contains("unix") || os.contains("linux")) { | ||
return LINUX; | ||
} | ||
throw new IllegalStateException("OS is unsupported: " + os); | ||
} | ||
|
||
private final String path; | ||
|
||
PlatformJavaPaths(String s) { | ||
path = s; | ||
} | ||
} |
90 changes: 90 additions & 0 deletions
90
...tect/src/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/probe/ProbeBuilder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection.probe; | ||
|
||
import static org.objectweb.asm.Opcodes.*; | ||
|
||
import com.google.common.base.Suppliers; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.function.Supplier; | ||
import org.objectweb.asm.ClassWriter; | ||
import org.objectweb.asm.Label; | ||
import org.objectweb.asm.MethodVisitor; | ||
|
||
// This is taken from Gradle internals | ||
public class ProbeBuilder { | ||
public static final String MARKER_PREFIX = "DCEVM_DETECT_PROBE_VALUE:"; | ||
|
||
public static void writeClass(Path probeFile) throws IOException { | ||
Files.createFile(probeFile); | ||
try (var stream = new FileOutputStream(probeFile.toFile())) { | ||
stream.write(probeClass.get()); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
private static final Supplier<byte[]> probeClass = Suppliers.memoize(ProbeBuilder::createProbeClass); | ||
|
||
private static byte[] createProbeClass() { | ||
ClassWriter cw = new ClassWriter(0); | ||
createClassHeader(cw); | ||
createConstructor(cw); | ||
createMainMethod(cw); | ||
cw.visitEnd(); | ||
return cw.toByteArray(); | ||
} | ||
|
||
private static void createClassHeader(ClassWriter cw) { | ||
cw.visit(V1_1, ACC_PUBLIC + ACC_SUPER, "JavaProbe", null, "java/lang/Object", null); | ||
} | ||
|
||
private static void createMainMethod(ClassWriter cw) { | ||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null); | ||
mv.visitCode(); | ||
Label l0 = new Label(); | ||
mv.visitLabel(l0); | ||
for (Props type : Props.values()) { | ||
dumpProperty(mv, type.getValue()); | ||
} | ||
mv.visitInsn(RETURN); | ||
Label l3 = new Label(); | ||
mv.visitLabel(l3); | ||
mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l3, 0); | ||
mv.visitMaxs(3, 1); | ||
mv.visitEnd(); | ||
} | ||
|
||
private static void dumpProperty(MethodVisitor mv, String property) { | ||
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); | ||
mv.visitLdcInsn(MARKER_PREFIX); | ||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "print", "(Ljava/lang/String;)V", false); | ||
|
||
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); | ||
mv.visitLdcInsn(property); | ||
mv.visitLdcInsn("unknown"); | ||
mv.visitMethodInsn( | ||
INVOKESTATIC, | ||
"java/lang/System", | ||
"getProperty", | ||
"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", | ||
false); | ||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); | ||
} | ||
|
||
private static void createConstructor(ClassWriter cw) { | ||
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); | ||
mv.visitCode(); | ||
Label l0 = new Label(); | ||
mv.visitLabel(l0); | ||
mv.visitVarInsn(ALOAD, 0); | ||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); | ||
mv.visitInsn(RETURN); | ||
Label l1 = new Label(); | ||
mv.visitLabel(l1); | ||
mv.visitLocalVariable("this", "LJavaProbe;", null, l0, l1, 0); | ||
mv.visitMaxs(1, 1); | ||
mv.visitEnd(); | ||
} | ||
} |
59 changes: 59 additions & 0 deletions
59
...c/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/probe/ProbeDcevmDetection.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection.probe; | ||
|
||
import static io.github.srdjanv.hotswapgradle.dcevmdetection.probe.PlatformJavaPaths.resolveExecutable; | ||
import static io.github.srdjanv.hotswapgradle.dcevmdetection.probe.ProbeBuilder.MARKER_PREFIX; | ||
|
||
import io.github.srdjanv.hotswapgradle.dcevmdetection.VMMeta; | ||
import io.github.srdjanv.hotswapgradle.dcevmdetection.VMReport; | ||
import java.io.BufferedReader; | ||
import java.io.InputStreamReader; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Arrays; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
public class ProbeDcevmDetection { | ||
public static VMReport buildReport(Path javaHome) { | ||
try { | ||
Path tempDir = Files.createTempDirectory("HotswapProbe"); | ||
tempDir.toFile().deleteOnExit(); | ||
Path tempFile = tempDir.resolve("JavaProbe.class"); | ||
ProbeBuilder.writeClass(tempFile); | ||
|
||
Process process = new ProcessBuilder( | ||
resolveExecutable(javaHome).toAbsolutePath().toString(), | ||
"-Xmx32m", | ||
"-Xms32m", | ||
"-cp", | ||
tempDir.toRealPath().toAbsolutePath().toString(), | ||
com.google.common.io.Files.getNameWithoutExtension(tempFile.toString())) | ||
.start(); | ||
|
||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); | ||
if (process.waitFor(3, TimeUnit.MINUTES)) { | ||
int exitValue = process.exitValue(); | ||
if (exitValue == 0) return parseExecOutput(reader.lines()); | ||
|
||
throw new Exception("Command returned unexpected result code: " | ||
+ exitValue + "\nError output:\n" | ||
+ reader.lines().collect(Collectors.joining(System.lineSeparator()))); | ||
} else throw new Exception("VM Timeout reached"); | ||
} catch (Exception exception) { | ||
return VMReport.exception(exception); | ||
} | ||
} | ||
|
||
public static VMReport parseExecOutput(Stream<String> out) { | ||
String[] split = out.filter(line -> line.startsWith(MARKER_PREFIX)) | ||
.map(line -> line.substring(MARKER_PREFIX.length())) | ||
.toArray(String[]::new); | ||
if (split.length != 2) | ||
return VMReport.exception(new Exception("Invalid output format: " + Arrays.toString(split))); | ||
|
||
boolean isDcevm = split[Props.VM_NAME.ordinal()].contains("Dynamic Code Evolution"); | ||
String dcevmVersion = split[Props.VM_VERSION.ordinal()]; | ||
return VMReport.of(new VMMeta(isDcevm, dcevmVersion)); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
dcevm-detect/src/main/java/io/github/srdjanv/hotswapgradle/dcevmdetection/probe/Props.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package io.github.srdjanv.hotswapgradle.dcevmdetection.probe; | ||
|
||
public enum Props { | ||
VM_NAME("java.vm.name"), | ||
VM_VERSION("java.vm.version"); | ||
|
||
private final String value; | ||
|
||
Props(String internal) { | ||
value = internal; | ||
} | ||
|
||
public String getValue() { | ||
return value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.