< prev index next >
src/java.base/share/classes/java/lang/ProcessBuilder.java
Print this page
imported patch ProcessEnvironment-race
@@ -23,10 +23,12 @@
* questions.
*/
package java.lang;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -207,11 +209,11 @@
* @param command the list containing the program and its arguments
*/
public ProcessBuilder(List<String> command) {
if (command == null)
throw new NullPointerException();
- this.command = command;
+ COMMAND.setRelease(this, command);
}
/**
* Constructs a process builder with the specified operating
* system program and arguments. This is a convenience
@@ -222,13 +224,14 @@
* command.
*
* @param command a string array containing the program and its arguments
*/
public ProcessBuilder(String... command) {
- this.command = new ArrayList<>(command.length);
+ List<String> commandList = new ArrayList<>(command.length);
for (String arg : command)
- this.command.add(arg);
+ commandList.add(arg);
+ COMMAND.setRelease(this, commandList);
}
/**
* Sets this process builder's operating system program and
* arguments. This method does <i>not</i> make a copy of the
@@ -241,11 +244,11 @@
* @return this process builder
*/
public ProcessBuilder command(List<String> command) {
if (command == null)
throw new NullPointerException();
- this.command = command;
+ COMMAND.setRelease(this, command);
return this;
}
/**
* Sets this process builder's operating system program and
@@ -272,11 +275,11 @@
* process builder.
*
* @return this process builder's program and its arguments
*/
public List<String> command() {
- return command;
+ return (List<String>) COMMAND.getAcquire(this);
}
/**
* Returns a string map view of this process builder's environment.
*
@@ -348,16 +351,19 @@
public Map<String,String> environment() {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkPermission(new RuntimePermission("getenv.*"));
- if (environment == null)
- environment = ProcessEnvironment.environment();
-
- assert environment != null;
-
+ // Multiple threads may call this method without synchronization
+ for (;;) {
+ Map<String,String> environment = (Map<String,String>)
+ ENVIRONMENT.getAcquire(this);
+ if (environment != null)
return environment;
+ ENVIRONMENT.compareAndSet(this, null,
+ ProcessEnvironment.environment());
+ }
}
// Only for use by Runtime.exec(...envp...)
ProcessBuilder environment(String[] envp) {
assert environment == null;
@@ -1296,6 +1302,21 @@
});
throw ex;
}
return processes;
}
+
+ // VarHandle mechanics
+ private static final VarHandle COMMAND;
+ private static final VarHandle ENVIRONMENT;
+ static {
+ try {
+ MethodHandles.Lookup l = MethodHandles.lookup();
+ COMMAND = l.findVarHandle(
+ ProcessBuilder.class, "command", List.class);
+ ENVIRONMENT = l.findVarHandle(
+ ProcessBuilder.class, "environment", Map.class);
+ } catch (ReflectiveOperationException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
}
< prev index next >