Windows, JNI: move around sources
Move the Java JNI sources to a separate package:
c.g.devtools.build.lib.windows.jni and
c.g.devtools.build.lib.windows.runfiles.
Make the native method declarations private,
create public wrapper methods for them that ensure
that the JNI library is loaded.
Split the C++ JNI source processes.cc into two
parts (processes-jni.cc and file-jni.cc), extract
common functionality to jni-util.{h,cc}.
This change preparse the code for Android rule
support on Windows, specifically it lets the
Android BusyBox use the file JNI library so it can
create junctions on Windows to work around long
path issues when calling external tools.
See https://github.com/bazelbuild/bazel/issues/3264
Change-Id: I7f1a746d73f822ae419d11b893a91f4eb45d64da
PiperOrigin-RevId: 160643355
diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD
index 3091e7f..2a469a4 100644
--- a/src/main/java/com/google/devtools/build/lib/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/BUILD
@@ -43,6 +43,8 @@
"//src/main/java/com/google/devtools/build/lib/sandbox:srcs",
"//src/main/java/com/google/devtools/build/lib/ssd:srcs",
"//src/main/java/com/google/devtools/build/lib/standalone:srcs",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni:srcs",
+ "//src/main/java/com/google/devtools/build/lib/windows/runfiles:srcs",
"//src/main/java/com/google/devtools/build/lib/worker:srcs",
"//src/main/java/com/google/devtools/build/skyframe:srcs",
"//src/main/java/com/google/devtools/common/options:srcs",
@@ -103,6 +105,7 @@
":preconditions",
":shell",
":vfs",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni",
"//src/main/java/com/google/devtools/common/options",
"//third_party:guava",
"//third_party:jsr305",
@@ -259,6 +262,7 @@
":os_util",
":unix",
":windows",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni:processes",
],
)
diff --git a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
index c6a4758..e4eaf8e 100644
--- a/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/util/ProcessUtils.java
@@ -15,7 +15,7 @@
package com.google.devtools.build.lib.util;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
-import com.google.devtools.build.lib.windows.WindowsProcesses;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
/**
* OS Process related utilities.
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
index e1eb08f..83707d2 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsFileSystem.java
@@ -24,6 +24,7 @@
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.Path.PathFactory;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
deleted file mode 100644
index 9aac2a7..0000000
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsProcesses.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2016 The Bazel Authors. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.devtools.build.lib.windows;
-
-import java.util.List;
-
-/**
- * Process management on Windows.
- */
-public class WindowsProcesses {
- public static final long INVALID = -1;
-
- private WindowsProcesses() {
- // Prevent construction
- }
-
- /**
- * returns the PID of the current process.
- */
- static native int nativeGetpid();
-
- /**
- * Creates a process with the specified Windows command line.
- *
- * <p>Appropriately quoting arguments is the responsibility of the caller.
- *
- * @param argv0 the binary to run; must be unquoted; must be either an absolute, normalized
- * Windows path with a drive letter (e.g. "c:\foo\bar app.exe") or a single file name (e.g.
- * "foo app.exe")
- * @param argvRest the rest of the command line, i.e. argv[1:] (needs to be quoted Windows style)
- * @param commandLine the command line (needs to be quoted Windows style)
- * @param env the environment of the new process. null means inherit that of the Bazel server
- * @param cwd the working directory of the new process. if null, the same as that of the current
- * process
- * @param stdoutFile the file the stdout should be redirected to. if null, nativeReadStdout will
- * work.
- * @param stderrFile the file the stdout should be redirected to. if null, nativeReadStderr will
- * work.
- * @return the opaque identifier of the created process
- */
- static native long nativeCreateProcess(
- String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile);
-
- /**
- * Writes data from the given array to the stdin of the specified process.
- *
- * <p>Blocks until either some data was written or the process is terminated.
- *
- * @return the number of bytes written
- */
- static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
-
- /** Returns an opaque identifier of stdout stream for the process. */
- static native long nativeGetStdout(long process);
-
- /** Returns am opaque identifier of stderr stream for the process. */
- static native long nativeGetStderr(long process);
-
- /**
- * Reads data from the stream into the given array. {@code stream} should come from {@link
- * #nativeGetStdout(long)} or {@link #nativeGetStderr(long)}.
- *
- * <p>Blocks until either some data was read or the process is terminated.
- *
- * @return the number of bytes read, 0 on EOF, or -1 if there was an error.
- */
- static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
-
- /**
- * Waits until the given process terminates. If timeout is non-negative, it indicates the number
- * of milliseconds before the call times out.
- *
- * <p>Return values:
- * <li>0: Process finished</li>
- * <li>1: Timeout</li>
- * <li>2: Something went wrong</li>
- */
- static native int nativeWaitFor(long process, long timeout);
-
- /**
- * Returns the exit code of the process. Throws {@code IllegalStateException} if something
- * goes wrong.
- */
- static native int nativeGetExitCode(long process);
-
- /**
- * Returns the process ID of the given process or -1 if there was an error.
- */
- static native int nativeGetProcessPid(long process);
-
- /**
- * Terminates the given process. Returns true if the termination was successful.
- */
- static native boolean nativeTerminate(long process);
-
- /**
- * Releases the native data structures associated with the process.
- *
- * <p>Calling any other method on the same process after this call will result in the JVM crashing
- * or worse.
- */
- static native void nativeDeleteProcess(long process);
-
- /**
- * Closes the stream
- *
- * @param stream should come from {@link #nativeGetStdout(long)} or {@link
- * #nativeGetStderr(long)}.
- */
- static native void nativeCloseStream(long stream);
-
- /**
- * Returns a string representation of the last error caused by any call on the given process or
- * the empty string if the last operation was successful.
- *
- * <p>Does <b>NOT</b> terminate the process if it is still running.
- *
- * <p>After this call returns, subsequent calls will return the empty string if there was no
- * failed operation in between.
- */
- static native String nativeProcessGetLastError(long process);
-
- static native String nativeStreamGetLastError(long process);
-
- public static int getpid() {
- WindowsJniLoader.loadJni();
- return nativeGetpid();
- }
-
- static String quoteCommandLine(List<String> argv) {
- StringBuilder result = new StringBuilder();
- for (int iArg = 0; iArg < argv.size(); iArg++) {
- if (iArg != 0) {
- result.append(" ");
- }
- String arg = argv.get(iArg);
- boolean hasSpace = arg.contains(" ");
- if (!arg.contains("\"") && !arg.contains("\\") && !hasSpace) {
- // fast path. Just append the input string.
- result.append(arg);
- } else {
- // We need to quote things if the argument contains a space.
- if (hasSpace) {
- result.append("\"");
- }
-
- for (int iChar = 0; iChar < arg.length(); iChar++) {
- boolean lastChar = iChar == arg.length() - 1;
- switch (arg.charAt(iChar)) {
- case '"':
- // Escape double quotes
- result.append("\\\"");
- break;
- case '\\':
- // Backslashes at the end of the string are quoted if we add quotes
- if (lastChar) {
- result.append(hasSpace ? "\\\\" : "\\");
- } else {
- // Backslashes everywhere else are quoted if they are followed by a
- // quote or a backslash
- result.append(arg.charAt(iChar + 1) == '"' || arg.charAt(iChar + 1) == '\\'
- ? "\\\\" : "\\");
- }
- break;
- default:
- result.append(arg.charAt(iChar));
- }
- }
- // Add ending quotes if we added a quote at the beginning.
- if (hasSpace) {
- result.append("\"");
- }
- }
- }
-
- return result.toString();
- }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
index 0aea491..59d9792 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocess.java
@@ -15,6 +15,7 @@
package com.google.devtools.build.lib.windows;
import com.google.devtools.build.lib.shell.Subprocess;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -57,7 +58,7 @@
*
* <p>This class is non-static for debugging purposes.
*/
- private class ProcessInputStream extends InputStream {
+ private static final class ProcessInputStream extends InputStream {
private long nativeStream;
ProcessInputStream(long nativeStream) {
@@ -75,18 +76,18 @@
}
@Override
- public synchronized int read(byte b[], int off, int len) throws IOException {
+ public synchronized int read(byte[] b, int off, int len) throws IOException {
if (nativeStream == WindowsProcesses.INVALID) {
throw new IllegalStateException();
}
- int result = WindowsProcesses.nativeReadStream(nativeStream, b, off, len);
+ int result = WindowsProcesses.readStream(nativeStream, b, off, len);
if (result == 0) {
return -1; // EOF
}
if (result == -1) {
- throw new IOException(WindowsProcesses.nativeStreamGetLastError(nativeStream));
+ throw new IOException(WindowsProcesses.streamGetLastError(nativeStream));
}
return result;
@@ -95,7 +96,7 @@
@Override
public synchronized void close() {
if (nativeStream != WindowsProcesses.INVALID) {
- WindowsProcesses.nativeCloseStream(nativeStream);
+ WindowsProcesses.closeStream(nativeStream);
nativeStream = WindowsProcesses.INVALID;
}
}
@@ -107,7 +108,7 @@
}
}
- private static AtomicInteger THREAD_SEQUENCE_NUMBER = new AtomicInteger(1);
+ private static final AtomicInteger THREAD_SEQUENCE_NUMBER = new AtomicInteger(1);
private static final ExecutorService WAITER_POOL = Executors.newCachedThreadPool(
new ThreadFactory() {
@Override
@@ -134,13 +135,9 @@
this.nativeProcess = nativeProcess;
this.timeoutMillis = timeoutMillis;
stdoutStream =
- stdoutRedirected
- ? null
- : new ProcessInputStream(WindowsProcesses.nativeGetStdout(nativeProcess));
+ stdoutRedirected ? null : new ProcessInputStream(WindowsProcesses.getStdout(nativeProcess));
stderrStream =
- stderrRedirected
- ? null
- : new ProcessInputStream(WindowsProcesses.nativeGetStderr(nativeProcess));
+ stderrRedirected ? null : new ProcessInputStream(WindowsProcesses.getStderr(nativeProcess));
stdinStream = new ProcessOutputStream();
waitLatch = new CountDownLatch(1);
// Every Windows process we start consumes a thread here. This is suboptimal, but seems to be
@@ -150,7 +147,7 @@
}
private void waiterThreadFunc() {
- switch (WindowsProcesses.nativeWaitFor(nativeProcess, timeoutMillis)) {
+ switch (WindowsProcesses.waitFor(nativeProcess, timeoutMillis)) {
case 0:
// Excellent, process finished in time.
break;
@@ -158,15 +155,15 @@
case 1:
// Timeout. Terminate the process if we can.
timedout.set(true);
- WindowsProcesses.nativeTerminate(nativeProcess);
+ WindowsProcesses.terminate(nativeProcess);
break;
case 2:
// Error. There isn't a lot we can do -- the process is still alive but
// WaitForMultipleObjects() failed for some odd reason. We'll pretend it terminated and
// log a message to jvm.out .
- System.err.println("Waiting for process "
- + WindowsProcesses.nativeGetProcessPid(nativeProcess) + " failed");
+ System.err.println(
+ "Waiting for process " + WindowsProcesses.getProcessPid(nativeProcess) + " failed");
break;
}
@@ -184,20 +181,15 @@
@Override
public synchronized boolean destroy() {
checkLiveness();
-
- if (!WindowsProcesses.nativeTerminate(nativeProcess)) {
- return false;
- }
-
- return true;
+ return WindowsProcesses.terminate(nativeProcess);
}
@Override
public synchronized int exitValue() {
checkLiveness();
- int result = WindowsProcesses.nativeGetExitCode(nativeProcess);
- String error = WindowsProcesses.nativeProcessGetLastError(nativeProcess);
+ int result = WindowsProcesses.getExitCode(nativeProcess);
+ String error = WindowsProcesses.processGetLastError(nativeProcess);
if (!error.isEmpty()) {
throw new IllegalStateException(error);
}
@@ -227,7 +219,7 @@
stderrStream.close();
long process = nativeProcess;
nativeProcess = WindowsProcesses.INVALID;
- WindowsProcesses.nativeDeleteProcess(process);
+ WindowsProcesses.deleteProcess(process);
}
}
@@ -252,12 +244,11 @@
int remaining = len;
int currentOffset = off;
while (remaining != 0) {
- int written = WindowsProcesses.nativeWriteStdin(
- nativeProcess, b, currentOffset, remaining);
+ int written = WindowsProcesses.writeStdin(nativeProcess, b, currentOffset, remaining);
// I think the Windows API never returns 0 in dwNumberOfBytesWritten
// Verify.verify(written != 0);
if (written == -1) {
- throw new IOException(WindowsProcesses.nativeProcessGetLastError(nativeProcess));
+ throw new IOException(WindowsProcesses.processGetLastError(nativeProcess));
}
remaining -= written;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
index e85325d..e398a3b 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/WindowsSubprocessFactory.java
@@ -19,6 +19,7 @@
import com.google.devtools.build.lib.shell.SubprocessBuilder;
import com.google.devtools.build.lib.shell.SubprocessBuilder.StreamAction;
import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import java.io.File;
import java.io.IOException;
import java.util.List;
@@ -37,11 +38,9 @@
@Override
public Subprocess create(SubprocessBuilder builder) throws IOException {
- WindowsJniLoader.loadJni();
-
List<String> argv = builder.getArgv();
- // DO NOT quote argv0, nativeCreateProcess will do it for us.
+ // DO NOT quote argv0, createProcess will do it for us.
String argv0 = processArgv0(argv.get(0));
String argvRest =
argv.size() > 1 ? WindowsProcesses.quoteCommandLine(argv.subList(1, argv.size())) : "";
@@ -51,11 +50,11 @@
String stderrPath = getRedirectPath(builder.getStderr(), builder.getStderrFile());
long nativeProcess =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
argv0, argvRest, env, builder.getWorkingDirectory().getPath(), stdoutPath, stderrPath);
- String error = WindowsProcesses.nativeProcessGetLastError(nativeProcess);
+ String error = WindowsProcesses.processGetLastError(nativeProcess);
if (!error.isEmpty()) {
- WindowsProcesses.nativeDeleteProcess(nativeProcess);
+ WindowsProcesses.deleteProcess(nativeProcess);
throw new IOException(error);
}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
new file mode 100644
index 0000000..ed8ca69
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/BUILD
@@ -0,0 +1,37 @@
+package(
+ default_visibility = [
+ "//src/main/java/com/google/devtools/build/lib:__subpackages__",
+ "//src/test/java/com/google/devtools/build/lib:__subpackages__",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "jni",
+ exports = [
+ ":file",
+ ":processes",
+ ],
+)
+
+java_library(
+ name = "file",
+ srcs = ["WindowsFileOperations.java"],
+ deps = [":jni-loader"],
+)
+
+java_library(
+ name = "processes",
+ srcs = ["WindowsProcesses.java"],
+ deps = [":jni-loader"],
+)
+
+java_library(
+ name = "jni-loader",
+ srcs = ["WindowsJniLoader.java"],
+ deps = ["//src/main/java/com/google/devtools/build/lib/windows/runfiles"],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
similarity index 93%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java
rename to src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
index 0d68c36..44b6cba 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsFileOperations.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsFileOperations.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
import java.io.IOException;
@@ -49,11 +49,11 @@
private static final int IS_JUNCTION_NO = 1;
private static final int IS_JUNCTION_ERROR = 2;
- static native int nativeIsJunction(String path, String[] error);
+ private static native int nativeIsJunction(String path, String[] error);
- static native boolean nativeGetLongPath(String path, String[] result, String[] error);
+ private static native boolean nativeGetLongPath(String path, String[] result, String[] error);
- static native boolean nativeCreateJunction(String name, String target, String[] error);
+ private static native boolean nativeCreateJunction(String name, String target, String[] error);
/** Determines whether `path` is a junction point or directory symlink. */
public static boolean isJunction(String path) throws IOException {
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
similarity index 88%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
rename to src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
index bc59eac..8b53d0c 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsJniLoader.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsJniLoader.java
@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.jni;
+import com.google.devtools.build.lib.windows.runfiles.WindowsRunfiles;
import java.io.IOException;
-/**
- * Loads native code under Windows.
- */
+/** Loads native code under Windows. */
public class WindowsJniLoader {
private static boolean jniLoaded = false;
+
public static synchronized void loadJni() {
if (jniLoaded) {
return;
diff --git a/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
new file mode 100644
index 0000000..1eaab25
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/jni/WindowsProcesses.java
@@ -0,0 +1,248 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.windows.jni;
+
+import java.util.List;
+
+/** Process management on Windows. */
+public class WindowsProcesses {
+ public static final long INVALID = -1;
+
+ private WindowsProcesses() {
+ // Prevent construction
+ }
+
+ /**
+ * Creates a process with the specified Windows command line.
+ *
+ * <p>Appropriately quoting arguments is the responsibility of the caller.
+ *
+ * @param argv0 the binary to run; must be unquoted; must be either an absolute, normalized
+ * Windows path with a drive letter (e.g. "c:\foo\bar app.exe") or a single file name (e.g.
+ * "foo app.exe")
+ * @param argvRest the rest of the command line, i.e. argv[1:] (needs to be quoted Windows style)
+ * @param commandLine the command line (needs to be quoted Windows style)
+ * @param env the environment of the new process. null means inherit that of the Bazel server
+ * @param cwd the working directory of the new process. if null, the same as that of the current
+ * process
+ * @param stdoutFile the file the stdout should be redirected to. if null, nativeReadStdout will
+ * work.
+ * @param stderrFile the file the stdout should be redirected to. if null, nativeReadStderr will
+ * work.
+ * @return the opaque identifier of the created process
+ */
+ public static long createProcess(
+ String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile) {
+ WindowsJniLoader.loadJni();
+ return nativeCreateProcess(argv0, argvRest, env, cwd, stdoutFile, stderrFile);
+ }
+
+ private static native long nativeCreateProcess(
+ String argv0, String argvRest, byte[] env, String cwd, String stdoutFile, String stderrFile);
+
+ /**
+ * Writes data from the given array to the stdin of the specified process.
+ *
+ * <p>Blocks until either some data was written or the process is terminated.
+ *
+ * @return the number of bytes written
+ */
+ public static int writeStdin(long process, byte[] bytes, int offset, int length) {
+ WindowsJniLoader.loadJni();
+ return nativeWriteStdin(process, bytes, offset, length);
+ }
+
+ private static native int nativeWriteStdin(long process, byte[] bytes, int offset, int length);
+
+ /** Returns an opaque identifier of stdout stream for the process. */
+ public static long getStdout(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetStdout(process);
+ }
+
+ private static native long nativeGetStdout(long process);
+
+ /** Returns an opaque identifier of stderr stream for the process. */
+ public static long getStderr(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetStderr(process);
+ }
+
+ private static native long nativeGetStderr(long process);
+
+ /**
+ * Reads data from the stream into the given array. {@code stream} should come from {@link
+ * #nativeGetStdout(long)} or {@link #nativeGetStderr(long)}.
+ *
+ * <p>Blocks until either some data was read or the process is terminated.
+ *
+ * @return the number of bytes read, 0 on EOF, or -1 if there was an error.
+ */
+ public static int readStream(long stream, byte[] bytes, int offset, int length) {
+ WindowsJniLoader.loadJni();
+ return nativeReadStream(stream, bytes, offset, length);
+ }
+
+ private static native int nativeReadStream(long stream, byte[] bytes, int offset, int length);
+
+ /**
+ * Waits until the given process terminates. If timeout is non-negative, it indicates the number
+ * of milliseconds before the call times out.
+ *
+ * <p>Return values:
+ * <li>0: Process finished
+ * <li>1: Timeout
+ * <li>2: Something went wrong
+ */
+ public static int waitFor(long process, long timeout) {
+ WindowsJniLoader.loadJni();
+ return nativeWaitFor(process, timeout);
+ }
+
+ private static native int nativeWaitFor(long process, long timeout);
+
+ /**
+ * Returns the exit code of the process. Throws {@code IllegalStateException} if something goes
+ * wrong.
+ */
+ public static int getExitCode(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetExitCode(process);
+ }
+
+ private static native int nativeGetExitCode(long process);
+
+ /** Returns the process ID of the given process or -1 if there was an error. */
+ public static int getProcessPid(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeGetProcessPid(process);
+ }
+
+ private static native int nativeGetProcessPid(long process);
+
+ /** Terminates the given process. Returns true if the termination was successful. */
+ public static boolean terminate(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeTerminate(process);
+ }
+
+ private static native boolean nativeTerminate(long process);
+
+ /**
+ * Releases the native data structures associated with the process.
+ *
+ * <p>Calling any other method on the same process after this call will result in the JVM crashing
+ * or worse.
+ */
+ public static void deleteProcess(long process) {
+ WindowsJniLoader.loadJni();
+ nativeDeleteProcess(process);
+ }
+
+ private static native void nativeDeleteProcess(long process);
+
+ /**
+ * Closes the stream
+ *
+ * @param stream should come from {@link #nativeGetStdout(long)} or {@link
+ * #nativeGetStderr(long)}.
+ */
+ public static void closeStream(long stream) {
+ WindowsJniLoader.loadJni();
+ nativeCloseStream(stream);
+ }
+
+ private static native void nativeCloseStream(long stream);
+
+ /**
+ * Returns a string representation of the last error caused by any call on the given process or
+ * the empty string if the last operation was successful.
+ *
+ * <p>Does <b>NOT</b> terminate the process if it is still running.
+ *
+ * <p>After this call returns, subsequent calls will return the empty string if there was no
+ * failed operation in between.
+ */
+ public static String processGetLastError(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeProcessGetLastError(process);
+ }
+
+ private static native String nativeProcessGetLastError(long process);
+
+ public static String streamGetLastError(long process) {
+ WindowsJniLoader.loadJni();
+ return nativeStreamGetLastError(process);
+ }
+
+ private static native String nativeStreamGetLastError(long process);
+
+ /** returns the PID of the current process. */
+ public static int getpid() {
+ WindowsJniLoader.loadJni();
+ return nativeGetpid();
+ }
+
+ private static native int nativeGetpid();
+
+ public static String quoteCommandLine(List<String> argv) {
+ StringBuilder result = new StringBuilder();
+ for (int iArg = 0; iArg < argv.size(); iArg++) {
+ if (iArg != 0) {
+ result.append(" ");
+ }
+ String arg = argv.get(iArg);
+ boolean hasSpace = arg.contains(" ");
+ if (!arg.contains("\"") && !arg.contains("\\") && !hasSpace) {
+ // fast path. Just append the input string.
+ result.append(arg);
+ } else {
+ // We need to quote things if the argument contains a space.
+ if (hasSpace) {
+ result.append("\"");
+ }
+
+ for (int iChar = 0; iChar < arg.length(); iChar++) {
+ boolean lastChar = iChar == arg.length() - 1;
+ switch (arg.charAt(iChar)) {
+ case '"':
+ // Escape double quotes
+ result.append("\\\"");
+ break;
+ case '\\':
+ // Backslashes at the end of the string are quoted if we add quotes
+ if (lastChar) {
+ result.append(hasSpace ? "\\\\" : "\\");
+ } else {
+ // Backslashes everywhere else are quoted if they are followed by a
+ // quote or a backslash
+ result.append(
+ arg.charAt(iChar + 1) == '"' || arg.charAt(iChar + 1) == '\\' ? "\\\\" : "\\");
+ }
+ break;
+ default:
+ result.append(arg.charAt(iChar));
+ }
+ }
+ // Add ending quotes if we added a quote at the beginning.
+ if (hasSpace) {
+ result.append("\"");
+ }
+ }
+ }
+
+ return result.toString();
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD b/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD
new file mode 100644
index 0000000..1ec264d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/windows/runfiles/BUILD
@@ -0,0 +1,16 @@
+package(
+ default_visibility = [
+ "//src/main/java/com/google/devtools/build/lib:__subpackages__",
+ "//src/test/java/com/google/devtools/build/lib:__subpackages__",
+ ],
+)
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+java_library(
+ name = "runfiles",
+ srcs = ["WindowsRunfiles.java"],
+)
diff --git a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java b/src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java
similarity index 96%
rename from src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java
rename to src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java
index 8765310..bf0d131 100644
--- a/src/main/java/com/google/devtools/build/lib/windows/WindowsRunfiles.java
+++ b/src/main/java/com/google/devtools/build/lib/windows/runfiles/WindowsRunfiles.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.devtools.build.lib.windows;
+package com.google.devtools.build.lib.windows.runfiles;
import java.io.BufferedReader;
import java.io.FileInputStream;
@@ -59,7 +59,7 @@
}
runfiles.put(splitLine[0], splitLine[1]);
- }
+ }
}
}
}
diff --git a/src/main/native/windows/file-jni.cc b/src/main/native/windows/file-jni.cc
new file mode 100644
index 0000000..78b3122
--- /dev/null
+++ b/src/main/native/windows/file-jni.cc
@@ -0,0 +1,84 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#define WIN32_LEAN_AND_MEAN
+#define WINVER 0x0601
+#define _WIN32_WINNT 0x0601
+
+#include <jni.h>
+#include <windows.h>
+
+#include <memory>
+#include <string>
+
+#include "src/main/native/windows/file.h"
+#include "src/main/native/windows/jni-util.h"
+#include "src/main/native/windows/util.h"
+
+static void MaybeReportLastError(const std::string& reason, JNIEnv* env,
+ jobjectArray error_msg_holder) {
+ if (error_msg_holder != nullptr &&
+ env->GetArrayLength(error_msg_holder) > 0) {
+ std::string error_str = bazel::windows::GetLastErrorString(reason);
+ jstring error_msg = env->NewStringUTF(error_str.c_str());
+ env->SetObjectArrayElement(error_msg_holder, 0, error_msg);
+ }
+}
+
+extern "C" JNIEXPORT jint JNICALL
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeIsJunction(
+ JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) {
+ int result = bazel::windows::IsJunctionOrDirectorySymlink(
+ bazel::windows::GetJavaWstring(env, path).c_str());
+ if (result == bazel::windows::IS_JUNCTION_ERROR) {
+ MaybeReportLastError(std::string("GetFileAttributes(") +
+ bazel::windows::GetJavaUTFString(env, path) + ")",
+ env, error_msg_holder);
+ }
+ return result;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeGetLongPath(
+ JNIEnv* env, jclass clazz, jstring path, jobjectArray result_holder,
+ jobjectArray error_msg_holder) {
+ std::unique_ptr<WCHAR[]> result;
+ bool success = bazel::windows::GetLongPath(
+ bazel::windows::GetJavaWstring(env, path).c_str(), &result);
+ if (!success) {
+ MaybeReportLastError(std::string("GetLongPathName(") +
+ bazel::windows::GetJavaUTFString(env, path) + ")",
+ env, error_msg_holder);
+ return JNI_FALSE;
+ }
+ env->SetObjectArrayElement(
+ result_holder, 0,
+ env->NewString(reinterpret_cast<const jchar*>(result.get()),
+ wcslen(result.get())));
+ return JNI_TRUE;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_google_devtools_build_lib_windows_jni_WindowsFileOperations_nativeCreateJunction(
+ JNIEnv* env, jclass clazz, jstring name, jstring target,
+ jobjectArray error_msg_holder) {
+ std::string error = bazel::windows::CreateJunction(
+ bazel::windows::GetJavaWstring(env, name),
+ bazel::windows::GetJavaWstring(env, target));
+ if (!error.empty()) {
+ MaybeReportLastError(error, env, error_msg_holder);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
diff --git a/src/main/native/windows/jni-util.cc b/src/main/native/windows/jni-util.cc
new file mode 100644
index 0000000..bba8957
--- /dev/null
+++ b/src/main/native/windows/jni-util.cc
@@ -0,0 +1,56 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include <type_traits> // static_assert
+
+#include "src/main/native/windows/jni-util.h"
+
+namespace bazel {
+namespace windows {
+
+using std::string;
+using std::wstring;
+
+// Ensure we can safely cast (const) jchar* to (const) WCHAR* and LP(C)WSTR.
+// This is true with MSVC but not always with GCC.
+static_assert(sizeof(jchar) == sizeof(WCHAR),
+ "jchar and WCHAR should be the same size");
+
+string GetJavaUTFString(JNIEnv* env, jstring str) {
+ string result;
+ if (str != nullptr) {
+ const char* jstr = env->GetStringUTFChars(str, nullptr);
+ result.assign(jstr);
+ env->ReleaseStringUTFChars(str, jstr);
+ }
+ return result;
+}
+
+wstring GetJavaWstring(JNIEnv* env, jstring str) {
+ wstring result;
+ if (str != nullptr) {
+ const jchar* jstr = env->GetStringChars(str, nullptr);
+ // We can safely reinterpret_cast because of the static_assert checking that
+ // sizeof(jchar) = sizeof(WCHAR).
+ result.assign(reinterpret_cast<const WCHAR*>(jstr));
+ env->ReleaseStringChars(str, jstr);
+ }
+ return result;
+}
+
+} // namespace windows
+} // namespace bazel
diff --git a/src/main/native/windows/jni-util.h b/src/main/native/windows/jni-util.h
new file mode 100644
index 0000000..c3632fd
--- /dev/null
+++ b/src/main/native/windows/jni-util.h
@@ -0,0 +1,30 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef BAZEL_SRC_MAIN_NATIVE_WINDOWS_JNI_UTIL_H_
+#define BAZEL_SRC_MAIN_NATIVE_WINDOWS_JNI_UTIL_H_
+
+#include <jni.h>
+
+#include <string>
+
+namespace bazel {
+namespace windows {
+
+std::string GetJavaUTFString(JNIEnv* env, jstring str);
+std::wstring GetJavaWstring(JNIEnv* env, jstring str);
+
+} // namespace windows
+} // namespace bazel
+
+#endif // BAZEL_SRC_MAIN_NATIVE_WINDOWS_JNI_UTIL_H_
diff --git a/src/main/native/windows/processes.cc b/src/main/native/windows/processes-jni.cc
similarity index 77%
rename from src/main/native/windows/processes.cc
rename to src/main/native/windows/processes-jni.cc
index 8900173..dd3e62c 100644
--- a/src/main/native/windows/processes.cc
+++ b/src/main/native/windows/processes-jni.cc
@@ -12,32 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
-#include <ctype.h>
#include <jni.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
#include <windows.h>
#include <atomic>
-#include <functional>
#include <memory>
#include <string>
-#include <type_traits> // static_assert
-#include "src/main/native/windows/file.h"
+#include "src/main/native/windows/jni-util.h"
#include "src/main/native/windows/util.h"
-// Ensure we can safely cast (const) jchar* to (const) WCHAR* and LP(C)WSTR.
-// This is true with MSVC but not always with GCC.
-static_assert(sizeof(jchar) == sizeof(WCHAR),
- "jchar and WCHAR should be the same size");
-
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetpid(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetpid(
JNIEnv* env, jclass clazz) {
return GetCurrentProcessId();
}
@@ -61,6 +51,10 @@
}
};
+static std::wstring AddUncPrefixMaybe(const std::wstring& path) {
+ return (path.size() >= MAX_PATH) ? (std::wstring(L"\\\\?\\") + path) : path;
+}
+
struct NativeProcess {
HANDLE stdin_;
NativeOutputStream stdout_;
@@ -118,53 +112,18 @@
version_info.dwMajorVersion == 6 && version_info.dwMinorVersion >= 2;
}
-static void MaybeReportLastError(const std::string& reason, JNIEnv* env,
- jobjectArray error_msg_holder) {
- if (error_msg_holder != nullptr &&
- env->GetArrayLength(error_msg_holder) > 0) {
- std::string error_str = bazel::windows::GetLastErrorString(reason);
- jstring error_msg = env->NewStringUTF(error_str.c_str());
- env->SetObjectArrayElement(error_msg_holder, 0, error_msg);
- }
-}
-
-static std::string GetJavaUTFString(JNIEnv* env, jstring str) {
- std::string result;
- if (str != nullptr) {
- const char* jstr = env->GetStringUTFChars(str, nullptr);
- result.assign(jstr);
- env->ReleaseStringUTFChars(str, jstr);
- }
- return result;
-}
-
-static std::wstring GetJavaWstring(JNIEnv* env, jstring str) {
- std::wstring result;
- if (str != nullptr) {
- const jchar* jstr = env->GetStringChars(str, nullptr);
- // We can safely reinterpret_cast because of the static_assert checking that
- // sizeof(jchar) = sizeof(WCHAR).
- result.assign(reinterpret_cast<const WCHAR*>(jstr));
- env->ReleaseStringChars(str, jstr);
- }
- return result;
-}
-
-static std::wstring AddUncPrefixMaybe(const std::wstring& path) {
- return (path.size() >= MAX_PATH) ? (std::wstring(L"\\\\?\\") + path) : path;
-}
-
static jlong PtrAsJlong(void* p) { return reinterpret_cast<jlong>(p); }
static std::string AsExecutableForCreateProcess(JNIEnv* env, jstring path,
std::string* result) {
return bazel::windows::AsExecutablePathForCreateProcess(
- GetJavaUTFString(env, path),
- [env, path]() { return GetJavaWstring(env, path); }, result);
+ bazel::windows::GetJavaUTFString(env, path),
+ [env, path]() { return bazel::windows::GetJavaWstring(env, path); },
+ result);
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCreateProcess(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeCreateProcess(
JNIEnv* env, jclass clazz, jstring java_argv0, jstring java_argv_rest,
jbyteArray java_env, jstring java_cwd, jstring java_stdout_redirect,
jstring java_stderr_redirect) {
@@ -177,15 +136,19 @@
return PtrAsJlong(result);
}
- std::string commandline = argv0 + " " + GetJavaUTFString(env, java_argv_rest);
- std::wstring stdout_redirect =
- AddUncPrefixMaybe(GetJavaWstring(env, java_stdout_redirect));
- std::wstring stderr_redirect =
- AddUncPrefixMaybe(GetJavaWstring(env, java_stderr_redirect));
+ std::string commandline =
+ argv0 + " " + bazel::windows::GetJavaUTFString(env, java_argv_rest);
+ std::wstring stdout_redirect = AddUncPrefixMaybe(
+ bazel::windows::GetJavaWstring(env, java_stdout_redirect));
+ std::wstring stderr_redirect = AddUncPrefixMaybe(
+ bazel::windows::GetJavaWstring(env, java_stderr_redirect));
std::string cwd;
error_msg = bazel::windows::AsShortPath(
- GetJavaUTFString(env, java_cwd),
- [env, java_cwd]() { return GetJavaWstring(env, java_cwd); }, &cwd);
+ bazel::windows::GetJavaUTFString(env, java_cwd),
+ [env, java_cwd]() {
+ return bazel::windows::GetJavaWstring(env, java_cwd);
+ },
+ &cwd);
if (!error_msg.empty()) {
result->error_ = error_msg;
return PtrAsJlong(result);
@@ -371,7 +334,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWriteStdin(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeWriteStdin(
JNIEnv* env, jclass clazz, jlong process_long, jbyteArray java_bytes,
jint offset, jint length) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -395,21 +358,21 @@
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetStdout(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetStdout(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
return PtrAsJlong(&process->stdout_);
}
extern "C" JNIEXPORT jlong JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetStderr(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetStderr(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
return PtrAsJlong(&process->stderr_);
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeReadStream(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeReadStream(
JNIEnv* env, jclass clazz, jlong stream_long, jbyteArray java_bytes,
jint offset, jint length) {
NativeOutputStream* stream =
@@ -448,7 +411,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetExitCode(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetExitCode(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
DWORD exit_code;
@@ -466,7 +429,7 @@
// 1: Timeout
// 2: Wait returned with an error
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeWaitFor(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeWaitFor(
JNIEnv* env, jclass clazz, jlong process_long, jlong java_timeout) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
HANDLE handles[1] = {process->process_};
@@ -515,7 +478,7 @@
}
extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeGetProcessPid(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeGetProcessPid(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
process->error_ = "";
@@ -523,7 +486,7 @@
}
extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeTerminate(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeTerminate(
JNIEnv* env, jclass clazz, jlong process_long) {
static const UINT exit_code = 130; // 128 + SIGINT, like on Linux
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -547,7 +510,7 @@
}
extern "C" JNIEXPORT void JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeDeleteProcess(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeDeleteProcess(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
@@ -570,7 +533,7 @@
}
extern "C" JNIEXPORT void JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeCloseStream(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeCloseStream(
JNIEnv* env, jclass clazz, jlong stream_long) {
NativeOutputStream* stream =
reinterpret_cast<NativeOutputStream*>(stream_long);
@@ -578,7 +541,7 @@
}
extern "C" JNIEXPORT jstring JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeProcessGetLastError(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeProcessGetLastError(
JNIEnv* env, jclass clazz, jlong process_long) {
NativeProcess* process = reinterpret_cast<NativeProcess*>(process_long);
jstring result = env->NewStringUTF(process->error_.c_str());
@@ -587,7 +550,7 @@
}
extern "C" JNIEXPORT jstring JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsProcesses_nativeStreamGetLastError(
+Java_com_google_devtools_build_lib_windows_jni_WindowsProcesses_nativeStreamGetLastError(
JNIEnv* env, jclass clazz, jlong stream_long) {
NativeOutputStream* stream =
reinterpret_cast<NativeOutputStream*>(stream_long);
@@ -595,49 +558,3 @@
stream->error_ = "";
return result;
}
-
-extern "C" JNIEXPORT jint JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeIsJunction(
- JNIEnv* env, jclass clazz, jstring path, jobjectArray error_msg_holder) {
- int result = bazel::windows::IsJunctionOrDirectorySymlink(
- GetJavaWstring(env, path).c_str());
- if (result == bazel::windows::IS_JUNCTION_ERROR) {
- MaybeReportLastError(
- std::string("GetFileAttributes(") + GetJavaUTFString(env, path) + ")",
- env, error_msg_holder);
- }
- return result;
-}
-
-extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeGetLongPath(
- JNIEnv* env, jclass clazz, jstring path, jobjectArray result_holder,
- jobjectArray error_msg_holder) {
- std::unique_ptr<WCHAR[]> result;
- bool success =
- bazel::windows::GetLongPath(GetJavaWstring(env, path).c_str(), &result);
- if (!success) {
- MaybeReportLastError(
- std::string("GetLongPathName(") + GetJavaUTFString(env, path) + ")",
- env, error_msg_holder);
- return JNI_FALSE;
- }
- env->SetObjectArrayElement(
- result_holder, 0,
- env->NewString(reinterpret_cast<const jchar*>(result.get()),
- wcslen(result.get())));
- return JNI_TRUE;
-}
-
-extern "C" JNIEXPORT jboolean JNICALL
-Java_com_google_devtools_build_lib_windows_WindowsFileOperations_nativeCreateJunction(
- JNIEnv* env, jclass clazz, jstring name, jstring target,
- jobjectArray error_msg_holder) {
- std::string error = bazel::windows::CreateJunction(
- GetJavaWstring(env, name), GetJavaWstring(env, target));
- if (!error.empty()) {
- MaybeReportLastError(error, env, error_msg_holder);
- return JNI_FALSE;
- }
- return JNI_TRUE;
-}
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 21766d7..fa97e1c 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -221,6 +221,8 @@
deps = [
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib:windows",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni",
+ "//src/main/java/com/google/devtools/build/lib/windows/runfiles",
"//third_party:guava",
"//third_party:guava-testlib",
"//third_party:junit4",
@@ -248,6 +250,7 @@
"//src/main/java/com/google/devtools/build/lib:os_util",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib:windows",
+ "//src/main/java/com/google/devtools/build/lib/windows/jni",
"//third_party:guava",
"//third_party:junit4",
"//third_party:truth",
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
index 1fd4223..107f620 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileOperationsTest.java
@@ -20,6 +20,7 @@
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.OS;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import com.google.devtools.build.lib.windows.util.WindowsTestUtil;
import java.io.File;
import java.io.IOException;
@@ -43,7 +44,6 @@
@Before
public void loadJni() throws Exception {
- WindowsTestUtil.loadJni();
scratchRoot = new File(System.getenv("TEST_TMPDIR")).getAbsolutePath() + "/x";
testUtil = new WindowsTestUtil(scratchRoot);
cleanupScratchDir();
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
index cd90fff5..7930957 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsFileSystemTest.java
@@ -29,6 +29,7 @@
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Symlinks;
import com.google.devtools.build.lib.windows.WindowsFileSystem.WindowsPath;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
import com.google.devtools.build.lib.windows.util.WindowsTestUtil;
import java.io.File;
import java.io.IOException;
@@ -55,7 +56,6 @@
@Before
public void loadJni() throws Exception {
- WindowsTestUtil.loadJni();
scratchRoot = new File(System.getenv("TEST_TMPDIR")).getAbsolutePath() + "/x";
testUtil = new WindowsTestUtil(scratchRoot);
fs = new WindowsFileSystem();
diff --git a/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java b/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
index 0c477cc..af5244d 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/WindowsProcessesTest.java
@@ -18,6 +18,7 @@
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.OS;
+import com.google.devtools.build.lib.windows.jni.WindowsProcesses;
import com.google.devtools.build.lib.windows.util.WindowsTestUtil;
import java.io.File;
import java.nio.charset.Charset;
@@ -49,16 +50,14 @@
"io_bazel/src/test/java/com/google/devtools/build/lib/MockSubprocess_deploy.jar");
mockBinary = System.getProperty("java.home") + "\\bin\\java.exe";
- WindowsJniLoader.loadJni();
-
process = -1;
}
@After
public void terminateProcess() throws Exception {
if (process != -1) {
- WindowsProcesses.nativeTerminate(process);
- WindowsProcesses.nativeDeleteProcess(process);
+ WindowsProcesses.terminate(process);
+ WindowsProcesses.deleteProcess(process);
process = -1;
}
}
@@ -75,26 +74,26 @@
}
private void assertNoProcessError() throws Exception {
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isEmpty();
+ assertThat(WindowsProcesses.processGetLastError(process)).isEmpty();
}
private void assertNoStreamError(long stream) throws Exception {
- assertThat(WindowsProcesses.nativeStreamGetLastError(stream)).isEmpty();
+ assertThat(WindowsProcesses.streamGetLastError(stream)).isEmpty();
}
@Test
public void testSmoke() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("Ia5", "Oa"), null, null, null, null);
assertNoProcessError();
byte[] input = "HELLO".getBytes(UTF8);
byte[] output = new byte[5];
- WindowsProcesses.nativeWriteStdin(process, input, 0, 5);
+ WindowsProcesses.writeStdin(process, input, 0, 5);
assertNoProcessError();
readStdout(output, 0, 5);
- assertNoStreamError(WindowsProcesses.nativeGetStdout(process));
+ assertNoStreamError(WindowsProcesses.getStdout(process));
assertThat(new String(output, UTF8)).isEqualTo("HELLO");
}
@@ -107,12 +106,12 @@
}
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs(args.toArray(new String[] {})), null, null, null, null);
for (int i = 0; i < 100; i++) {
byte[] input = String.format("%03d", i).getBytes(UTF8);
assertThat(input.length).isEqualTo(3);
- assertThat(WindowsProcesses.nativeWriteStdin(process, input, 0, 3)).isEqualTo(3);
+ assertThat(WindowsProcesses.writeStdin(process, input, 0, 3)).isEqualTo(3);
byte[] output = new byte[3];
assertThat(readStdout(output, 0, 3)).isEqualTo(3);
assertThat(Integer.parseInt(new String(output, UTF8))).isEqualTo(i);
@@ -120,36 +119,36 @@
}
private int readStdout(byte[] output, int offset, int length) {
- return WindowsProcesses.nativeReadStream(
- WindowsProcesses.nativeGetStdout(process), output, offset, length);
+ return WindowsProcesses.readStream(
+ WindowsProcesses.getStdout(process), output, offset, length);
}
private int readStderr(byte[] output, int offset, int length) {
- return WindowsProcesses.nativeReadStream(
- WindowsProcesses.nativeGetStderr(process), output, offset, length);
+ return WindowsProcesses.readStream(
+ WindowsProcesses.getStderr(process), output, offset, length);
}
@Test
public void testExitCode() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs("X42"), null, null, null, null);
- assertThat(WindowsProcesses.nativeWaitFor(process, -1)).isEqualTo(0);
- assertThat(WindowsProcesses.nativeGetExitCode(process)).isEqualTo(42);
+ WindowsProcesses.createProcess(mockBinary, mockArgs("X42"), null, null, null, null);
+ assertThat(WindowsProcesses.waitFor(process, -1)).isEqualTo(0);
+ assertThat(WindowsProcesses.getExitCode(process)).isEqualTo(42);
assertNoProcessError();
}
@Test
public void testPartialRead() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O-HELLO"), null, null, null, null);
byte[] one = new byte[2];
byte[] two = new byte[3];
assertThat(readStdout(one, 0, 2)).isEqualTo(2);
- assertNoStreamError(WindowsProcesses.nativeGetStdout(process));
+ assertNoStreamError(WindowsProcesses.getStdout(process));
assertThat(readStdout(two, 0, 3)).isEqualTo(3);
- assertNoStreamError(WindowsProcesses.nativeGetStdout(process));
+ assertNoStreamError(WindowsProcesses.getStdout(process));
assertThat(new String(one, UTF8)).isEqualTo("HE");
assertThat(new String(two, UTF8)).isEqualTo("LLO");
@@ -158,7 +157,7 @@
@Test
public void testArrayOutOfBounds() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs("O-oob"), null, null, null, null);
+ WindowsProcesses.createProcess(mockBinary, mockArgs("O-oob"), null, null, null, null);
byte[] buf = new byte[3];
assertThat(readStdout(buf, -1, 3)).isEqualTo(-1);
assertThat(readStdout(buf, 0, 5)).isEqualTo(-1);
@@ -172,13 +171,13 @@
assertThat(readStderr(buf, 2, -1)).isEqualTo(-1);
assertThat(readStderr(buf, Integer.MAX_VALUE, 2)).isEqualTo(-1);
assertThat(readStderr(buf, 2, Integer.MAX_VALUE)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, -1, 3)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, 0, 5)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, 4, 1)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, 2, -1)).isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, Integer.MAX_VALUE, 2))
+ assertThat(WindowsProcesses.writeStdin(process, buf, -1, 3)).isEqualTo(-1);
+ assertThat(WindowsProcesses.writeStdin(process, buf, 0, 5)).isEqualTo(-1);
+ assertThat(WindowsProcesses.writeStdin(process, buf, 4, 1)).isEqualTo(-1);
+ assertThat(WindowsProcesses.writeStdin(process, buf, 2, -1)).isEqualTo(-1);
+ assertThat(WindowsProcesses.writeStdin(process, buf, Integer.MAX_VALUE, 2))
.isEqualTo(-1);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, 2, Integer.MAX_VALUE))
+ assertThat(WindowsProcesses.writeStdin(process, buf, 2, Integer.MAX_VALUE))
.isEqualTo(-1);
assertThat(readStdout(buf, 0, 3)).isEqualTo(3);
@@ -188,12 +187,12 @@
@Test
public void testOffsetedOps() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("Ia3", "Oa"), null, null, null, null);
byte[] input = "01234".getBytes(UTF8);
byte[] output = "abcde".getBytes(UTF8);
- assertThat(WindowsProcesses.nativeWriteStdin(process, input, 1, 3)).isEqualTo(3);
+ assertThat(WindowsProcesses.writeStdin(process, input, 1, 3)).isEqualTo(3);
assertNoProcessError();
int rv = readStdout(output, 1, 3);
assertNoProcessError();
@@ -205,7 +204,7 @@
@Test
public void testParallelStdoutAndStderr() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary,
mockArgs(
"O-out1", "E-err1", "O-out2", "E-err2", "E-err3", "O-out3", "E-err4", "O-out4"),
@@ -239,9 +238,9 @@
@Test
public void testExecutableNotFound() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
"ThisExecutableDoesNotExist", "TheseArgsDontMatter", null, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process))
+ assertThat(WindowsProcesses.processGetLastError(process))
.contains("The system cannot find the file specified.");
byte[] buf = new byte[1];
assertThat(readStdout(buf, 0, 1)).isEqualTo(0);
@@ -250,18 +249,18 @@
@Test
public void testReadingAndWritingAfterTermination() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs("X42"), null, null, null, null);
+ WindowsProcesses.createProcess(mockBinary, mockArgs("X42"), null, null, null, null);
byte[] buf = new byte[1];
assertThat(readStdout(buf, 0, 1)).isEqualTo(0);
assertThat(readStderr(buf, 0, 1)).isEqualTo(0);
- assertThat(WindowsProcesses.nativeWriteStdin(process, buf, 0, 1)).isEqualTo(-1);
+ assertThat(WindowsProcesses.writeStdin(process, buf, 0, 1)).isEqualTo(-1);
}
@Test
public void testNewEnvironmentVariables() throws Exception {
byte[] data = "ONE=one\0TWO=twotwo\0\0".getBytes(UTF8);
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O$ONE", "O$TWO"), data, null, null, null);
assertNoProcessError();
byte[] buf = new byte[3];
@@ -275,36 +274,36 @@
@Test
public void testNoZeroInEnvBuffer() throws Exception {
byte[] data = "clown".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs(), data, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isNotEmpty();
+ process = WindowsProcesses.createProcess(mockBinary, mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.processGetLastError(process)).isNotEmpty();
}
@Test
public void testMissingFinalDoubleZeroInEnvBuffer() throws Exception {
byte[] data = "FOO=bar\0".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs(), data, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isNotEmpty();
+ process = WindowsProcesses.createProcess(mockBinary, mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.processGetLastError(process)).isNotEmpty();
}
@Test
public void testOneByteEnvBuffer() throws Exception {
byte[] data = "a".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs(), data, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isNotEmpty();
+ process = WindowsProcesses.createProcess(mockBinary, mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.processGetLastError(process)).isNotEmpty();
}
@Test
public void testOneZeroEnvBuffer() throws Exception {
byte[] data = "\0".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs(), data, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isNotEmpty();
+ process = WindowsProcesses.createProcess(mockBinary, mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.processGetLastError(process)).isNotEmpty();
}
@Test
public void testTwoZerosInEnvBuffer() throws Exception {
byte[] data = "\0\0".getBytes(UTF8);
- process = WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs(), data, null, null, null);
- assertThat(WindowsProcesses.nativeProcessGetLastError(process)).isEmpty();
+ process = WindowsProcesses.createProcess(mockBinary, mockArgs(), data, null, null, null);
+ assertThat(WindowsProcesses.processGetLastError(process)).isEmpty();
}
@Test
@@ -313,12 +312,12 @@
String stderrFile = System.getenv("TEST_TMPDIR") + "\\stderr_redirect";
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O-one", "E-two"), null, null, stdoutFile, stderrFile);
assertThat(process).isGreaterThan(0L);
assertNoProcessError();
- assertThat(WindowsProcesses.nativeWaitFor(process, -1)).isEqualTo(0);
- WindowsProcesses.nativeGetExitCode(process);
+ assertThat(WindowsProcesses.waitFor(process, -1)).isEqualTo(0);
+ WindowsProcesses.getExitCode(process);
assertNoProcessError();
byte[] stdout = Files.readAllBytes(Paths.get(stdoutFile));
byte[] stderr = Files.readAllBytes(Paths.get(stderrFile));
@@ -331,12 +330,12 @@
String file = System.getenv("TEST_TMPDIR") + "\\captured_";
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O-one", "E-two"), null, null, file, file);
assertThat(process).isGreaterThan(0L);
assertNoProcessError();
- assertThat(WindowsProcesses.nativeWaitFor(process, -1)).isEqualTo(0);
- WindowsProcesses.nativeGetExitCode(process);
+ assertThat(WindowsProcesses.waitFor(process, -1)).isEqualTo(0);
+ WindowsProcesses.getExitCode(process);
assertNoProcessError();
byte[] bytes = Files.readAllBytes(Paths.get(file));
assertThat(new String(bytes, UTF8)).isEqualTo("onetwo");
@@ -348,13 +347,13 @@
String stderrFile = System.getenv("TEST_TMPDIR") + "\\captured_stderr";
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O-one", "E-two"), null, null, stdoutFile, stderrFile);
assertNoProcessError();
byte[] buf = new byte[1];
assertThat(readStdout(buf, 0, 1)).isEqualTo(0);
assertThat(readStderr(buf, 0, 1)).isEqualTo(0);
- WindowsProcesses.nativeWaitFor(process, -1);
+ WindowsProcesses.waitFor(process, -1);
}
@Test
@@ -367,11 +366,11 @@
Files.write(stderr, "err1".getBytes(UTF8));
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("O-out2", "E-err2"), null, null, stdoutFile, stderrFile);
assertNoProcessError();
- WindowsProcesses.nativeWaitFor(process, -1);
- WindowsProcesses.nativeGetExitCode(process);
+ WindowsProcesses.waitFor(process, -1);
+ WindowsProcesses.getExitCode(process);
assertNoProcessError();
byte[] stdoutBytes = Files.readAllBytes(Paths.get(stdoutFile));
byte[] stderrBytes = Files.readAllBytes(Paths.get(stderrFile));
@@ -385,7 +384,7 @@
new File(dir1).mkdir();
process =
- WindowsProcesses.nativeCreateProcess(mockBinary, mockArgs("O."), null, dir1, null, null);
+ WindowsProcesses.createProcess(mockBinary, mockArgs("O."), null, dir1, null, null);
assertNoProcessError();
byte[] buf = new byte[1024]; // Windows MAX_PATH is 260, but whatever
int len = readStdout(buf, 0, 1024);
@@ -396,8 +395,8 @@
@Test
public void testTimeout() throws Exception {
process =
- WindowsProcesses.nativeCreateProcess(
+ WindowsProcesses.createProcess(
mockBinary, mockArgs("W5", "X0"), null, null, null, null);
- assertThat(WindowsProcesses.nativeWaitFor(process, 1000)).isEqualTo(1);
+ assertThat(WindowsProcesses.waitFor(process, 1000)).isEqualTo(1);
}
}
diff --git a/src/test/java/com/google/devtools/build/lib/windows/util/WindowsTestUtil.java b/src/test/java/com/google/devtools/build/lib/windows/util/WindowsTestUtil.java
index 7a73b57..620565c 100644
--- a/src/test/java/com/google/devtools/build/lib/windows/util/WindowsTestUtil.java
+++ b/src/test/java/com/google/devtools/build/lib/windows/util/WindowsTestUtil.java
@@ -21,9 +21,8 @@
import com.google.common.base.Strings;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
-import com.google.devtools.build.lib.windows.WindowsFileOperations;
-import com.google.devtools.build.lib.windows.WindowsJniLoader;
-import com.google.devtools.build.lib.windows.WindowsRunfiles;
+import com.google.devtools.build.lib.windows.jni.WindowsFileOperations;
+import com.google.devtools.build.lib.windows.runfiles.WindowsRunfiles;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -42,11 +41,6 @@
this.scratchRoot = scratchRoot;
}
- /** Ensure the actual JNI DLL is loaded. */
- public static void loadJni() {
- WindowsJniLoader.loadJni();
- }
-
/**
* Create directory junctions then assert their existence.
*