Skip to content

Commit

Permalink
#47: Initial POC of connecting to another VM
Browse files Browse the repository at this point in the history
  • Loading branch information
Octogonapus committed Jun 21, 2020
1 parent aca3df4 commit 06b8723
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 44 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,6 @@ gradle-app.setting
# VSCode Project
.classpath
.project
.settings
.settings

*.hprof
6 changes: 6 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 121 additions & 0 deletions .idea/modules.xml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@
*/
package com.octogonapus.omj.agent;

import com.octogonapus.omj.util.Util;
import com.octogonapus.omj.util.JarExtractor;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class AgentLibJarExtractor {

private static File agentLibAllJar = null;
private static final Logger logger = LoggerFactory.getLogger(AgentLibJarExtractor.class);

/**
* Extracts the agent-lib jar from our jar and into a file.
*
Expand All @@ -37,40 +30,6 @@ public final class AgentLibJarExtractor {
*/
@SuppressWarnings("ResultOfMethodCallIgnored")
public static File extractJar() throws IOException {
try (final var agentLib = ClassLoader.getSystemResourceAsStream("agent-lib-all")) {
if (agentLib == null) {
throw new IOException("Could not locate agent-lib-all resource.");
}

// Extract the Jar and save it to agentLibAllJar so that subsequent calls do not try to
// extract the Jar again.
if (agentLibAllJar == null) {
Util.getAgentLibJarDir().toFile().mkdirs();
final var file = Util.getAgentLibJarDir().resolve("agent-lib-all.jar").toFile();
logger.debug("Extracting agent-lib-all.jar into {}", file.getAbsolutePath());
file.createNewFile();
copyStreamToFile(file, agentLib);
agentLibAllJar = file;
}

return agentLibAllJar;
}
}

private static void copyStreamToFile(File file, InputStream lib) throws IOException {
try (final var os = Files.newOutputStream(file.toPath())) {
final var buffer = new byte[0xFFFF];
int readBytes;
while (true) {
readBytes = lib.read(buffer);

// -1 means end of stream
if (readBytes == -1) {
break;
}

os.write(buffer, 0, readBytes);
}
}
return JarExtractor.extractJar("agent-lib-all");
}
}
9 changes: 9 additions & 0 deletions agent/src/main/kotlin/com/octogonapus/omj/agent/Agent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ object Agent {

@JvmStatic
fun premain(args: String?, instrumentation: Instrumentation) {
mainImpl(instrumentation)
}

@JvmStatic
fun agentmain(args: String?, instrumentation: Instrumentation) {
mainImpl(instrumentation)
}

private fun mainImpl(instrumentation: Instrumentation) {
OMJKoinContext.koinApp = koinApplication {
modules(
module {
Expand Down
45 changes: 45 additions & 0 deletions ui/src/main/kotlin/com/octogonapus/omj/ui/AgentLoader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* This file is part of OMJ.
*
* OMJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OMJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OMJ. If not, see <https://www.gnu.org/licenses/>.
*/
package com.octogonapus.omj.ui

import com.octogonapus.omj.util.JarExtractor
import com.sun.tools.attach.AttachNotSupportedException
import com.sun.tools.attach.VirtualMachine
import java.io.IOException
import java.lang.management.ManagementFactory

object AgentLoader {

fun loadAgent() {
val name = ManagementFactory.getRuntimeMXBean().name
val pid = name.substring(0, name.indexOf('@'))
try {
val virtualMachine = VirtualMachine.attach(pid)
val agentJar = JarExtractor.extractJar("agent-all")
virtualMachine.loadAgent(agentJar.absolutePath, null)
virtualMachine.detach()
} catch (e: AttachNotSupportedException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
}

fun main() {
AgentLoader.loadAgent()
}
71 changes: 71 additions & 0 deletions util/src/main/java/com/octogonapus/omj/util/JarExtractor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* This file is part of OMJ.
*
* OMJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OMJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OMJ. If not, see <https://www.gnu.org/licenses/>.
*/
package com.octogonapus.omj.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

public class JarExtractor {

private static final Map<String, File> resourceMap = new HashMap<>();

/**
* Extracts the agent-lib jar from our jar and into a file.
*
* @return The file the agent-lib jar is extracted into.
* @throws IOException Any IO problems along the way. All fatal.
*/
public static File extractJar(final String resourceName) throws IOException {
try (final var agentLib = ClassLoader.getSystemResourceAsStream(resourceName)) {
if (agentLib == null) {
throw new IOException("Could not locate resource: " + resourceName);
}

// Extract the Jar and save it so that subsequent calls do not try to extract the Jar again.
if (!resourceMap.containsKey(resourceName)) {
final var file =
Files.createTempFile(Util.getAgentLibJarDir(), resourceName + '_', ".jar").toFile();
file.deleteOnExit();
copyStreamToFile(file, agentLib);
resourceMap.put(resourceName, file);
}

return resourceMap.get(resourceName);
}
}

private static void copyStreamToFile(File file, InputStream lib) throws IOException {
try (final var os = Files.newOutputStream(file.toPath())) {
final var buffer = new byte[0xFFFF];
int readBytes;
while (true) {
readBytes = lib.read(buffer);

// -1 means end of stream
if (readBytes == -1) {
break;
}

os.write(buffer, 0, readBytes);
}
}
}
}

0 comments on commit 06b8723

Please sign in to comment.