Skip to content

Commit

Permalink
Merge d6e2ad9 into 1c5f2e9
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyMacDroo committed Jan 12, 2019
2 parents 1c5f2e9 + d6e2ad9 commit 0e4222a
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 38 deletions.
9 changes: 8 additions & 1 deletion localstack/ext/java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,14 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.20</version>
<version>1.18.4</version>
<scope>provided</scope>
</dependency>
<!-- required to build on java 9+ -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,11 +424,12 @@ public void killAll(Map<String, String> modelEnvVars) throws InterruptedExceptio
}

static abstract class Unix extends Local {

@Override
public OSProcess get(Process proc) {
try {
return get((Integer) UnixReflection.PID_FIELD.get(proc));
} catch (IllegalAccessException e) { // impossible
return get((Integer) UnixReflection.pid(proc));
} catch (IllegalAccessError e) { // impossible
IllegalAccessError x = new IllegalAccessError();
x.initCause(e);
throw x;
Expand Down Expand Up @@ -533,58 +534,90 @@ public void killRecursively() throws InterruptedException {
private static final class UnixReflection {
/**
* Field to access the PID of the process.
* Required for Java 8 and older JVMs.
*/
private static final Field JAVA8_PID_FIELD;

/**
* Field to access the PID of the process.
* Required for Java 9 and above until this is replaced by multi-release JAR.
*/
private static final Field PID_FIELD;
private static final Method JAVA9_PID_METHOD;

/**
* Method to destroy a process, given pid.
*
* Looking at the JavaSE source code, this is using SIGTERM (15)
*/
private static final Method DESTROY_PROCESS;
private static final Method JAVA8_DESTROY_PROCESS;
private static final Method JAVA_9_PROCESSHANDLE_OF;
private static final Method JAVA_9_PROCESSHANDLE_DESTROY;

static {
try {
Class<?> clazz = Class.forName("java.lang.UNIXProcess");
PID_FIELD = clazz.getDeclaredField("pid");
PID_FIELD.setAccessible(true);

if (isPreJava8()) {
DESTROY_PROCESS = clazz.getDeclaredMethod("destroyProcess", int.class);
if (isPostJava8()) {
Class<?> clazz = Process.class;
JAVA9_PID_METHOD = clazz.getMethod("pid");
JAVA8_PID_FIELD = null;
Class<?> processHandleClazz = Class.forName("java.lang.ProcessHandle");
JAVA_9_PROCESSHANDLE_OF = processHandleClazz.getMethod("of", long.class);
JAVA_9_PROCESSHANDLE_DESTROY = processHandleClazz.getMethod("destroy");
JAVA8_DESTROY_PROCESS = null;
} else {
DESTROY_PROCESS = clazz.getDeclaredMethod("destroyProcess", int.class, boolean.class);
Class<?> clazz = Class.forName("java.lang.UNIXProcess");
JAVA8_PID_FIELD = clazz.getDeclaredField("pid");
JAVA8_PID_FIELD.setAccessible(true);
JAVA9_PID_METHOD = null;

JAVA8_DESTROY_PROCESS = clazz.getDeclaredMethod("destroyProcess", int.class, boolean.class);
JAVA8_DESTROY_PROCESS.setAccessible(true);
JAVA_9_PROCESSHANDLE_OF = null;
JAVA_9_PROCESSHANDLE_DESTROY = null;
}
DESTROY_PROCESS.setAccessible(true);
} catch (ClassNotFoundException e) {
LinkageError x = new LinkageError();
x.initCause(e);
throw x;
} catch (NoSuchFieldException e) {
LinkageError x = new LinkageError();
x.initCause(e);
throw x;
} catch (NoSuchMethodException e) {
LinkageError x = new LinkageError();
x.initCause(e);
} catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException e) {
LinkageError x = new LinkageError("Cannot initialize reflection for Unix Processes", e);
throw x;
}
}

public static void destroy(int pid) throws IllegalAccessException, InvocationTargetException {
if (isPreJava8()) {
DESTROY_PROCESS.invoke(null, pid);
public static void destroy(int pid) throws IllegalAccessException,
InvocationTargetException {
if (JAVA8_DESTROY_PROCESS != null) {
JAVA8_DESTROY_PROCESS.invoke(null, pid, false);
} else {
DESTROY_PROCESS.invoke(null, pid, false);
final Optional handle = (Optional)JAVA_9_PROCESSHANDLE_OF.invoke(null, pid);
if (handle.isPresent()) {
JAVA_9_PROCESSHANDLE_DESTROY.invoke(handle.get());
}
}
}

private static boolean isPreJava8() {
int javaVersionAsAnInteger = Integer.parseInt(System.getProperty("java.version")
.replaceAll("\\.", "")
.replaceAll("_", "")
.substring(0, 2));
return javaVersionAsAnInteger < 18;
public static int pid(Process proc) {
try {
if (JAVA8_PID_FIELD != null) {
return JAVA8_PID_FIELD.getInt(proc);
} else {
long pid = (long) JAVA9_PID_METHOD.invoke(proc);
if (pid > Integer.MAX_VALUE) {
throw new IllegalAccessError("PID is out of bounds: " + pid);
}
return (int) pid;
}
} catch (IllegalAccessException | InvocationTargetException e) { // impossible
IllegalAccessError x = new IllegalAccessError();
x.initCause(e);
throw x;
}
}

private static String getJavaVersionFromSystemProperty(){
return System.getProperty("java.version");
}

private static boolean isPostJava8(){
return !getJavaVersionFromSystemProperty().startsWith("1.");
}

}

static class Linux extends ProcfsUnix {
Expand Down Expand Up @@ -1121,12 +1154,12 @@ public static abstract class Local extends ProcessTree {
* instead you'd do it with the sysctl
* <http://search.cpan.org/src/DURIST/Proc-ProcessTable-0.42/os/darwin.c>
* <http://developer.apple.com/documentation/Darwin/Reference/ManPages/man3/sysctl.3.html>
*
*
* There's CLI but that doesn't seem to offer the access to per-process info
* <http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/sysctl.8.html>
*
*
*
*
*
*
* On HP-UX, pstat_getcommandline get you command line, but I'm not seeing any environment
* variables.
*/
Expand Down

0 comments on commit 0e4222a

Please sign in to comment.