Repository: incubator-reef
Updated Branches:
  refs/heads/master aee7bebf5 -> 1da62700f


[REEF-327] Allow users to set additional JVM options

- Add method addOption / isOptionSet to JVMProcess and JavaLaunchCommandBuilder.
- Revise runtimes to use isOptionSet to enforce heap slack only when no user
  options are set.
- Parse a subset of JVM option formats, and prevent duplicates of
  those options.
- Expand and add generics to EvaluatorProcess, EvaluatorProcessFactory,
  LaunchCommandBuilder interfaces. These should not break existing code.
- Provide an example for adding options at HelloJVMOptionsREEF/Driver.

JIRA:
  [REEF-327](https://issues.apache.org/jira/browse/REEF-327)

Pull Request:
  This closes #311


Project: http://git-wip-us.apache.org/repos/asf/incubator-reef/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-reef/commit/1da62700
Tree: http://git-wip-us.apache.org/repos/asf/incubator-reef/tree/1da62700
Diff: http://git-wip-us.apache.org/repos/asf/incubator-reef/diff/1da62700

Branch: refs/heads/master
Commit: 1da62700f3dc80fe684a0d7ccba99fe215fb5ca9
Parents: aee7beb
Author: Brian Cho <[email protected]>
Authored: Wed Jul 22 22:10:21 2015 +0900
Committer: Markus Weimer <[email protected]>
Committed: Thu Jul 30 09:42:04 2015 -0700

----------------------------------------------------------------------
 .../reef/driver/evaluator/CLRProcess.java       |  15 +-
 .../driver/evaluator/CLRProcessFactory.java     |   4 +-
 .../reef/driver/evaluator/EvaluatorProcess.java |  12 ++
 .../evaluator/EvaluatorProcessFactory.java      |   4 +-
 .../reef/driver/evaluator/JVMProcess.java       |  31 +++-
 .../driver/evaluator/JVMProcessFactory.java     |   4 +-
 .../common/launch/JavaLaunchCommandBuilder.java | 123 +++++++++++++-
 .../common/launch/LaunchCommandBuilder.java     |   5 +
 .../reef/driver/evaluator/JVMProcessTest.java   |  50 ++++++
 .../reef/driver/evaluator/package-info.java     |  22 +++
 .../launch/JavaLaunchCommandBuilderTest.java    | 169 +++++++++++++++++++
 .../runtime/common/launch/package-info.java     |  22 +++
 .../examples/hello/HelloJVMOptionsDriver.java   |  97 +++++++++++
 .../examples/hello/HelloJVMOptionsREEF.java     |  88 ++++++++++
 .../runtime/local/driver/ResourceManager.java   |  21 ++-
 .../driver/MesosResourceLaunchHandler.java      |  22 ++-
 .../yarn/driver/YARNResourceLaunchHandler.java  |  29 +++-
 17 files changed, 675 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcess.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcess.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcess.java
index 92704fa..2faff66 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcess.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcess.java
@@ -27,6 +27,7 @@ import java.util.List;
  */
 public final class CLRProcess implements EvaluatorProcess {
   private final CLRLaunchCommandBuilder commandBuilder = new 
CLRLaunchCommandBuilder();
+  private boolean optionSet = false;
 
   /**
    * Instantiated via CLRProcessFactory.
@@ -46,25 +47,31 @@ public final class CLRProcess implements EvaluatorProcess {
   }
 
   @Override
-  public EvaluatorProcess setMemory(final int megaBytes) {
+  public CLRProcess setMemory(final int megaBytes) {
     commandBuilder.setMemory(megaBytes);
+    optionSet = true;
     return this;
   }
 
   @Override
-  public EvaluatorProcess setConfigurationFileName(final String 
configurationFileName) {
+  public boolean isOptionSet() {
+    return optionSet;
+  }
+
+  @Override
+  public CLRProcess setConfigurationFileName(final String 
configurationFileName) {
     commandBuilder.setConfigurationFileName(configurationFileName);
     return this;
   }
 
   @Override
-  public EvaluatorProcess setStandardOut(final String standardOut) {
+  public CLRProcess setStandardOut(final String standardOut) {
     commandBuilder.setStandardOut(standardOut);
     return this;
   }
 
   @Override
-  public EvaluatorProcess setStandardErr(final String standardErr) {
+  public CLRProcess setStandardErr(final String standardErr) {
     commandBuilder.setStandardErr(standardErr);
     return this;
   }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcessFactory.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcessFactory.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcessFactory.java
index d5d3d3e..d352bcf 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcessFactory.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/CLRProcessFactory.java
@@ -28,13 +28,13 @@ import javax.inject.Inject;
  */
 @Private
 @DriverSide
-public final class CLRProcessFactory implements EvaluatorProcessFactory {
+public final class CLRProcessFactory implements 
EvaluatorProcessFactory<CLRProcess> {
   @Inject
   private CLRProcessFactory() {
   }
 
   @Override
-  public EvaluatorProcess newEvaluatorProcess() {
+  public CLRProcess newEvaluatorProcess() {
     return new CLRProcess();
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcess.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcess.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcess.java
index ff4b5b1..ef6096a 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcess.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcess.java
@@ -22,6 +22,9 @@ import java.util.List;
 
 /**
  * Defines the setup of an evaluator's process.
+ * Users can set custom options via {@link #setMemory(int)} and process-type 
specific methods.
+ * Runtimes can also set options, but should not do so if users have set 
options by
+ * checking {@link #isOptionSet()}.
  */
 public interface EvaluatorProcess {
   /**
@@ -43,6 +46,15 @@ public interface EvaluatorProcess {
   EvaluatorProcess setMemory(final int megaBytes);
 
   /**
+   * Check whether custom options have been set for the process.
+   * Options are memory given via {@link #setMemory(int)} and any other custom 
options
+   * supported by the specific type of evaluator process.
+   *
+   * @return whether custom options have been set for the process
+   */
+  boolean isOptionSet();
+
+  /**
    * Set the name of the configuration file for the Launcher. This file is 
assumed to exist in the working directory of
    * the process launched with this command line.
    *

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcessFactory.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcessFactory.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcessFactory.java
index 2f32f09..057fb34 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcessFactory.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/EvaluatorProcessFactory.java
@@ -28,6 +28,6 @@ import org.apache.reef.tang.annotations.DefaultImplementation;
 @Public
 @DriverSide
 @DefaultImplementation(JVMProcessFactory.class)
-public interface EvaluatorProcessFactory {
-  EvaluatorProcess newEvaluatorProcess();
+public interface EvaluatorProcessFactory<T> {
+  <T extends EvaluatorProcess> T newEvaluatorProcess();
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcess.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcess.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcess.java
index 8ed2a14..98f4d14 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcess.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcess.java
@@ -26,17 +26,21 @@ import java.util.List;
 
 /**
  * Defines the setup of a JVM process.
+ * Users can set JVM options via {@link #setMemory(int)} and {@link 
#addOption(String)}.
+ * Runtimes can also set JVM options, but should not do so if users have set 
options by
+ * checking {@link #isOptionSet()}.
  */
 public final class JVMProcess implements EvaluatorProcess {
   private final JavaLaunchCommandBuilder commandBuilder = new 
JavaLaunchCommandBuilder();
   private final RuntimePathProvider runtimePathProvider;
   private final ClasspathProvider classpathProvider;
+  private boolean optionSet = false;
 
   /**
    * Instantiated via JVMProcessFactory.
    */
   JVMProcess(final RuntimePathProvider runtimePathProvider,
-                    final ClasspathProvider classpathProvider) {
+             final ClasspathProvider classpathProvider) {
     this.runtimePathProvider = runtimePathProvider;
     this.classpathProvider = classpathProvider;
   }
@@ -55,26 +59,43 @@ public final class JVMProcess implements EvaluatorProcess {
   }
 
   @Override
-  public EvaluatorProcess setMemory(final int megaBytes) {
+  public JVMProcess setMemory(final int megaBytes) {
     commandBuilder.setMemory(megaBytes);
+    optionSet = true;
     return this;
   }
 
   @Override
-  public EvaluatorProcess setConfigurationFileName(final String 
configurationFileName) {
+  public boolean isOptionSet() {
+    return optionSet;
+  }
+
+  @Override
+  public JVMProcess setConfigurationFileName(final String 
configurationFileName) {
     commandBuilder.setConfigurationFileName(configurationFileName);
     return this;
   }
 
   @Override
-  public EvaluatorProcess setStandardOut(final String standardOut) {
+  public JVMProcess setStandardOut(final String standardOut) {
     commandBuilder.setStandardOut(standardOut);
     return this;
   }
 
   @Override
-  public EvaluatorProcess setStandardErr(final String standardErr) {
+  public JVMProcess setStandardErr(final String standardErr) {
     commandBuilder.setStandardErr(standardErr);
     return this;
   }
+
+  /**
+   * Add a JVM option.
+   * @param option The full option, e.g. "-XX:+PrintGCDetails", "-Xms500m"
+   * @return this
+   */
+  public JVMProcess addOption(final String option) {
+    commandBuilder.addOption(option);
+    optionSet = true;
+    return this;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcessFactory.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcessFactory.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcessFactory.java
index e986fd5..f82d718 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcessFactory.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/driver/evaluator/JVMProcessFactory.java
@@ -28,7 +28,7 @@ import javax.inject.Inject;
  * Factory to setup new JVM processes.
  */
 @DriverSide
-public final class JVMProcessFactory implements EvaluatorProcessFactory {
+public final class JVMProcessFactory implements 
EvaluatorProcessFactory<JVMProcess> {
   private final RuntimePathProvider pathProvider;
   private final ClasspathProvider classpathProvider;
 
@@ -40,7 +40,7 @@ public final class JVMProcessFactory implements 
EvaluatorProcessFactory {
   }
 
   @Override
-  public EvaluatorProcess newEvaluatorProcess() {
+  public JVMProcess newEvaluatorProcess() {
     return new JVMProcess(pathProvider, classpathProvider);
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilder.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilder.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilder.java
index 24e36a6..9fdf50f 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilder.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilder.java
@@ -25,17 +25,34 @@ import org.apache.reef.util.EnvironmentUtils;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 public final class JavaLaunchCommandBuilder implements LaunchCommandBuilder {
+  private static final Logger LOG = 
Logger.getLogger(JavaLaunchCommandBuilder.class.getName());
+
   private static final String DEFAULT_JAVA_PATH = System.getenv("JAVA_HOME") + 
"/bin/" + "java";
+  private static final String[] DEFAULT_OPTIONS = {"-XX:PermSize=128m", 
"-XX:MaxPermSize=128m"};
   private String stderrPath = null;
   private String stdoutPath = null;
-  private int megaBytes = 0;
   private String evaluatorConfigurationPath = null;
   private String javaPath = null;
   private String classPath = null;
   private Boolean assertionsEnabled = null;
+  private Map<String, JVMOption> options = new HashMap<>();
+
+  /**
+   * Constructor that populates default options.
+   */
+  public JavaLaunchCommandBuilder() {
+    for (final String defaultOption : DEFAULT_OPTIONS) {
+      addOption(defaultOption);
+    }
+  }
 
   @Override
   public List<String> build() {
@@ -47,14 +64,13 @@ public final class JavaLaunchCommandBuilder implements 
LaunchCommandBuilder {
           add(javaPath);
         }
 
-        add("-XX:PermSize=128m");
-        add("-XX:MaxPermSize=128m");
-        // Set Xmx based on am memory size
-        add("-Xmx" + megaBytes + "m");
-
         if ((assertionsEnabled != null && assertionsEnabled)
             || EnvironmentUtils.areAssertionsEnabled()) {
-          add("-ea");
+          addOption("-ea");
+        }
+
+        for (final JVMOption jvmOption : options.values()) {
+          add(jvmOption.toString());
         }
 
         if (classPath != null && !classPath.isEmpty()) {
@@ -84,8 +100,7 @@ public final class JavaLaunchCommandBuilder implements 
LaunchCommandBuilder {
   @Override
   @SuppressWarnings("checkstyle:hiddenfield")
   public JavaLaunchCommandBuilder setMemory(final int megaBytes) {
-    this.megaBytes = megaBytes;
-    return this;
+    return addOption(JVMOption.parse("-Xmx" + megaBytes + "m"));
   }
 
   @Override
@@ -128,6 +143,23 @@ public final class JavaLaunchCommandBuilder implements 
LaunchCommandBuilder {
   }
 
   /**
+   * Add a JVM option.
+   * @param option The full option, e.g. "-XX:+PrintGCDetails"
+   * @return this
+   */
+  public JavaLaunchCommandBuilder addOption(final String option) {
+    return addOption(JVMOption.parse(option));
+  }
+
+  private JavaLaunchCommandBuilder addOption(final JVMOption jvmOption) {
+    if (options.containsKey(jvmOption.option)) {
+      LOG.warning("Replaced option " + options.get(jvmOption.option) + " with 
" + jvmOption);
+    }
+    options.put(jvmOption.option, jvmOption);
+    return this;
+  }
+
+  /**
    * Enable or disable assertions on the child process.
    * If not set, the setting is taken from the JVM that executes the code.
    *
@@ -139,4 +171,77 @@ public final class JavaLaunchCommandBuilder implements 
LaunchCommandBuilder {
     this.assertionsEnabled = assertionsEnabled;
     return this;
   }
+
+  /**
+   * Represents the JVM option as a option and value, combined by a separator.
+   * There are many different JVM option formats. This implementation only 
recognizes
+   * equals-separated and -Xm[nsx] memory options. All other option formats are
+   * represented with an option and empty value and separator.
+   */
+  static final class JVMOption {
+    static final Pattern EQUALS = Pattern.compile("(.+)=(.+)");
+    static final Pattern MEMORY = Pattern.compile("(\\-Xm[nsx])(.+)");
+
+    public final String option;
+    public final String value;
+    public final String separator;
+
+    private JVMOption(final String option, final String value,
+                     final String separator) {
+      this.option = option;
+      this.value = value;
+      this.separator = separator;
+    }
+
+    static JVMOption parse(final String string) {
+
+      final String trimmed = string.trim();
+
+      final Matcher equalsMatcher = EQUALS.matcher(trimmed);
+      if (equalsMatcher.matches()) {
+        return new JVMOption(equalsMatcher.group(1), equalsMatcher.group(2), 
"=");
+      }
+
+      final Matcher memoryMatcher = MEMORY.matcher(trimmed);
+      if (memoryMatcher.matches()) {
+        return new JVMOption(memoryMatcher.group(1), memoryMatcher.group(2), 
"");
+      }
+
+      // Unknown options return the entire string as the option
+      return new JVMOption(trimmed, "", "");
+    }
+
+    public String toString() {
+      return option + separator + value;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+
+      final JVMOption jvmOption = (JVMOption) o;
+
+      if (!option.equals(jvmOption.option)) {
+        return false;
+      }
+      if (!value.equals(jvmOption.value)) {
+        return false;
+      }
+      return separator.equals(jvmOption.separator);
+
+    }
+
+    @Override
+    public int hashCode() {
+      int result = option.hashCode();
+      result = 31 * result + value.hashCode();
+      result = 31 * result + separator.hashCode();
+      return result;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/LaunchCommandBuilder.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/LaunchCommandBuilder.java
 
b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/LaunchCommandBuilder.java
index 5726980..0768298 100644
--- 
a/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/LaunchCommandBuilder.java
+++ 
b/lang/java/reef-common/src/main/java/org/apache/reef/runtime/common/launch/LaunchCommandBuilder.java
@@ -31,6 +31,11 @@ public interface LaunchCommandBuilder {
    */
   List<String> build();
 
+  /**
+   * Set the size of the launched process in megabytes.
+   * @param megaBytes
+   * @return this
+   */
   LaunchCommandBuilder setMemory(final int megaBytes);
 
   /**

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/JVMProcessTest.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/JVMProcessTest.java
 
b/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/JVMProcessTest.java
new file mode 100644
index 0000000..0446213
--- /dev/null
+++ 
b/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/JVMProcessTest.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.reef.driver.evaluator;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Tests for JVMProcess.
+ */
+public final class JVMProcessTest {
+
+  @Test
+  public void testIsOptionSetFalse() {
+    final JVMProcess jvmProcess = new JVMProcess(null, null);
+    assertFalse("Option not set", jvmProcess.isOptionSet());
+  }
+
+  @Test
+  public void testIsOptionSet() {
+    final JVMProcess jvmProcess = new JVMProcess(null, null)
+        .addOption("-XX:+HeapDumpOnOutOfMemory");
+    assertTrue("Option set", jvmProcess.isOptionSet());
+  }
+
+  @Test
+  public void testIsOptionSetOnMemory() {
+    final JVMProcess jvmProcess = new JVMProcess(null, null)
+        .setMemory(500);
+    assertTrue("Option set", jvmProcess.isOptionSet());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/package-info.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/package-info.java
 
b/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/package-info.java
new file mode 100644
index 0000000..47f78e5
--- /dev/null
+++ 
b/lang/java/reef-common/src/test/java/org/apache/reef/driver/evaluator/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+/**
+ * Tests for Evaluator management on the Driver.
+ */
+package org.apache.reef.driver.evaluator;

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilderTest.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilderTest.java
 
b/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilderTest.java
new file mode 100644
index 0000000..8a2f0ae
--- /dev/null
+++ 
b/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/JavaLaunchCommandBuilderTest.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.reef.runtime.common.launch;
+
+import org.junit.Test;
+
+import java.util.List;
+
+import static 
org.apache.reef.runtime.common.launch.JavaLaunchCommandBuilder.JVMOption;
+import static org.junit.Assert.*;
+
+public final class JavaLaunchCommandBuilderTest {
+
+  @Test
+  public void testParseEqualsOption() {
+    final JVMOption equals = JVMOption.parse("-XX:PermSize=128m");
+    assertEquals("-XX:PermSize", equals.option);
+    assertEquals("128m", equals.value);
+    assertEquals("=", equals.separator);
+    assertEquals("-XX:PermSize=128m", equals.toString());
+  }
+
+  @Test
+  public void testParseMemoryOption() {
+    final JVMOption xmx = JVMOption.parse("-Xmx500m");
+    assertEquals("-Xmx", xmx.option);
+    assertEquals("500m", xmx.value);
+    assertEquals("", xmx.separator);
+    assertEquals("-Xmx500m", xmx.toString());
+  }
+
+  @Test
+  public void testParseUnknownOption() {
+    final JVMOption unknown = JVMOption.parse("-XX:+HeapDumpOnOutOfMemory");
+    assertEquals("-XX:+HeapDumpOnOutOfMemory", unknown.option);
+    assertEquals("", unknown.value);
+    assertEquals("", unknown.separator);
+    assertEquals("-XX:+HeapDumpOnOutOfMemory", unknown.toString());
+  }
+
+  @Test
+  public void testJVMOptionEquals() {
+    // Option parsed with the EQUALS pattern
+    final JVMOption permSize1 = JVMOption.parse("-XX:PermSize=128m");
+    final JVMOption permSize2 = JVMOption.parse("-XX:PermSize=128m");
+    assertTrue(permSize1.equals(permSize2));
+    assertTrue(permSize2.equals(permSize1));
+    final JVMOption permSize3 = JVMOption.parse("-XX:PermSize=64m");
+    assertFalse(permSize1.equals(permSize3));
+    assertFalse(permSize3.equals(permSize1));
+
+    // Option parsed with the MEMORY pattern
+    final JVMOption memory1 = JVMOption.parse("-Xmx500m");
+    final JVMOption memory2 = JVMOption.parse("-Xmx500m");
+    assertTrue(memory1.equals(memory2));
+    assertTrue(memory2.equals(memory1));
+
+    final JVMOption memory3 = JVMOption.parse("-Xmx300m");
+    assertFalse(memory1.equals(memory3));
+    assertFalse(memory3.equals(memory1));
+
+    // Option with an unknown pattern
+    final JVMOption unknown1 = JVMOption.parse("-XX:+HeapDumpOnOutOfMemory");
+    final JVMOption unknown2 = JVMOption.parse("-XX:+HeapDumpOnOutOfMemory");
+    assertTrue(unknown1.equals(unknown2));
+    assertTrue(unknown2.equals(unknown1));
+
+    final JVMOption unknown3 = JVMOption.parse("-XX:+PrintGCDetails");
+    assertFalse(unknown1.equals(unknown3));
+    assertFalse(unknown3.equals(unknown1));
+  }
+
+  @Test
+  public void testSetMemory() {
+    final List<String> command = newBuilder()
+        .setMemory(300)
+        .build();
+    assertMemoryOption(command, "300m");
+  }
+
+  @Test
+  public void testOverrideMemory() {
+    final List<String> command = newBuilder()
+        .setMemory(300)
+        .setMemory(500)
+        .build();
+    assertMemoryOption(command, "500m");
+  }
+
+  @Test
+  public void testAddMemoryOption() {
+    final List<String> command = newBuilder()
+        .addOption("-Xmx900m")
+        .build();
+    assertMemoryOption(command, "900m");
+  }
+
+  @Test
+  public void testOverrideMemoryOption() {
+    final List<String> command = newBuilder()
+        .setMemory(300)
+        .addOption("-Xmx900m")
+        .build();
+    assertMemoryOption(command, "900m");
+  }
+
+  private static void assertMemoryOption(final List<String> command, final 
String memoryValue) {
+    int numMemoryEntries = 0;
+    for (final String entry : command) {
+      if (entry.startsWith("-Xmx")) {
+        numMemoryEntries++;
+        assertTrue("-Xmx set to value", entry.endsWith(memoryValue));
+      }
+    }
+    assertEquals(1, numMemoryEntries);
+  }
+
+  @Test
+  public void testPermSizeDefaults() {
+    final List<String> command = newBuilder()
+        .build();
+    assertPermSizeSet(command, "128m", "128m");
+  }
+
+  @Test
+  public void testAddPermSizeOptions() {
+    final List<String> command = newBuilder()
+        .addOption(" -XX:PermSize=256m ")
+        .addOption(" -XX:MaxPermSize=512m    ")
+        .build();
+    assertPermSizeSet(command, "256m", "512m");
+  }
+
+  private static void assertPermSizeSet(final List<String> command, final 
String permSize, final String maxPermSize) {
+    int numPermSizeEntries = 0;
+    int numMaxPermSizeEntries = 0;
+    for (final String entry : command) {
+      if (entry.startsWith("-XX:PermSize")) {
+        numPermSizeEntries++;
+        assertTrue("-XX:PermSize set to value", entry.endsWith(permSize));
+      } else if (entry.startsWith("-XX:MaxPermSize")) {
+        numMaxPermSizeEntries++;
+        assertTrue("-XX:MaxPermSize set to value", 
entry.endsWith(maxPermSize));
+      }
+    }
+    assertEquals(1, numPermSizeEntries);
+    assertEquals(1, numMaxPermSizeEntries);
+  }
+
+  private static JavaLaunchCommandBuilder newBuilder() {
+    return new 
JavaLaunchCommandBuilder().setConfigurationFileName("mockConfigurationFileName");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/package-info.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/package-info.java
 
b/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/package-info.java
new file mode 100644
index 0000000..2b9abf1
--- /dev/null
+++ 
b/lang/java/reef-common/src/test/java/org/apache/reef/runtime/common/launch/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+/**
+ * Tests for common launch code between Driver and Evaluator.
+ */
+package org.apache.reef.runtime.common.launch;

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsDriver.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsDriver.java
 
b/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsDriver.java
new file mode 100644
index 0000000..4c04adf
--- /dev/null
+++ 
b/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsDriver.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.reef.examples.hello;
+
+import org.apache.reef.driver.evaluator.AllocatedEvaluator;
+import org.apache.reef.driver.evaluator.EvaluatorRequest;
+import org.apache.reef.driver.evaluator.EvaluatorRequestor;
+import org.apache.reef.driver.evaluator.JVMProcess;
+import org.apache.reef.driver.evaluator.JVMProcessFactory;
+import org.apache.reef.driver.task.TaskConfiguration;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.annotations.Unit;
+import org.apache.reef.wake.EventHandler;
+import org.apache.reef.wake.time.event.StartTime;
+
+import javax.inject.Inject;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * The Driver code for the Hello JVM Options Application.
+ * The additional JVM Options print out diagnostics at the Evaluator.
+ */
+@Unit
+public final class HelloJVMOptionsDriver {
+
+  private static final Logger LOG = 
Logger.getLogger(HelloJVMOptionsDriver.class.getName());
+
+  private final EvaluatorRequestor requestor;
+  private final JVMProcessFactory jvmProcessFactory;
+
+  /**
+   * Job driver constructor - instantiated via TANG.
+   *
+   * @param requestor evaluator requestor object used to create new evaluator 
containers.
+   */
+  @Inject
+  public HelloJVMOptionsDriver(final EvaluatorRequestor requestor,
+                               final JVMProcessFactory jvmProcessFactory) {
+    this.requestor = requestor;
+    this.jvmProcessFactory = jvmProcessFactory;
+    LOG.log(Level.FINE, "Instantiated 'HelloDriver'");
+  }
+
+  /**
+   * Handles the StartTime event: Request as single Evaluator.
+   */
+  public final class StartHandler implements EventHandler<StartTime> {
+    @Override
+    public void onNext(final StartTime startTime) {
+      HelloJVMOptionsDriver.this.requestor.submit(EvaluatorRequest.newBuilder()
+          .setNumber(1)
+          .setMemory(64)
+          .setNumberOfCores(1)
+          .build());
+      LOG.log(Level.INFO, "Requested Evaluator.");
+    }
+  }
+
+  /**
+   * Handles AllocatedEvaluator: Submit the HelloTask with additional JVM 
Options.
+   * The additional JVM Options print out diagnostics at the Evaluator.
+   */
+  public final class EvaluatorAllocatedHandler implements 
EventHandler<AllocatedEvaluator> {
+    @Override
+    public void onNext(final AllocatedEvaluator allocatedEvaluator) {
+      LOG.log(Level.INFO, "Submitting HelloREEF task to AllocatedEvaluator: 
{0}", allocatedEvaluator);
+      final Configuration taskConfiguration = TaskConfiguration.CONF
+          .set(TaskConfiguration.IDENTIFIER, "HelloREEFTask")
+          .set(TaskConfiguration.TASK, HelloTask.class)
+          .build();
+      final JVMProcess jvmProcess = jvmProcessFactory.newEvaluatorProcess()
+          .setMemory(56)
+          .addOption("-Xdiag")
+          .addOption("-XX:+PrintCommandLineFlags")
+          .addOption("-XX:+PrintGCDetails");
+      allocatedEvaluator.setProcess(jvmProcess);
+      allocatedEvaluator.submitTask(taskConfiguration);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsREEF.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsREEF.java
 
b/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsREEF.java
new file mode 100644
index 0000000..960fd5e
--- /dev/null
+++ 
b/lang/java/reef-examples/src/main/java/org/apache/reef/examples/hello/HelloJVMOptionsREEF.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.reef.examples.hello;
+
+import org.apache.reef.client.DriverConfiguration;
+import org.apache.reef.client.DriverLauncher;
+import org.apache.reef.client.LauncherStatus;
+import org.apache.reef.runtime.local.client.LocalRuntimeConfiguration;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.InjectionException;
+import org.apache.reef.util.EnvironmentUtils;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * The Client for Hello JVM Options example.
+ * Launches HelloJVMOptionsDriver.
+ */
+public final class HelloJVMOptionsREEF {
+  private static final Logger LOG = 
Logger.getLogger(HelloJVMOptionsREEF.class.getName());
+
+  /**
+   * The upper limit on the number of Evaluators that the local 
resourcemanager will hand out concurrently.
+   */
+  private static final int MAX_NUMBER_OF_EVALUATORS = 2;
+
+  /**
+   * Number of milliseconds to wait for the job to complete.
+   */
+  private static final int JOB_TIMEOUT = 10000; // 10 sec.
+
+  /**
+   * @return the configuration of the HelloREEF driver.
+   */
+  public static Configuration getDriverConfiguration() {
+    return DriverConfiguration.CONF
+        .set(DriverConfiguration.GLOBAL_LIBRARIES, 
EnvironmentUtils.getClassLocation(HelloJVMOptionsDriver.class))
+        .set(DriverConfiguration.DRIVER_IDENTIFIER, "HelloJVMOptions")
+        .set(DriverConfiguration.ON_DRIVER_STARTED, 
HelloJVMOptionsDriver.StartHandler.class)
+        .set(DriverConfiguration.ON_EVALUATOR_ALLOCATED, 
HelloJVMOptionsDriver.EvaluatorAllocatedHandler.class)
+        .build();
+  }
+
+  public static LauncherStatus runHelloReef(final Configuration runtimeConf, 
final int timeOut)
+      throws BindException, InjectionException {
+    final Configuration driverConf = getDriverConfiguration();
+    return DriverLauncher.getLauncher(runtimeConf).run(driverConf, timeOut);
+  }
+
+  /**
+   * Start Hello REEF job. Runs method runHelloReef().
+   *
+   * @param args command line parameters.
+   * @throws BindException      configuration error.
+   * @throws InjectionException configuration error.
+   */
+  public static void main(final String[] args) throws BindException, 
InjectionException {
+    final Configuration runtimeConfiguration = LocalRuntimeConfiguration.CONF
+        .set(LocalRuntimeConfiguration.MAX_NUMBER_OF_EVALUATORS, 
MAX_NUMBER_OF_EVALUATORS)
+        .build();
+    final LauncherStatus status = runHelloReef(runtimeConfiguration, 
JOB_TIMEOUT);
+    LOG.log(Level.INFO, "REEF job completed: {0}", status);
+  }
+
+    /**
+     * Empty private constructor to prohibit instantiation of utility class.
+     */
+  private HelloJVMOptionsREEF() {
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ResourceManager.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ResourceManager.java
 
b/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ResourceManager.java
index 5c26cb9..ba498e2 100644
--- 
a/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ResourceManager.java
+++ 
b/lang/java/reef-runtime-local/src/main/java/org/apache/reef/runtime/local/driver/ResourceManager.java
@@ -20,6 +20,7 @@ package org.apache.reef.runtime.local.driver;
 
 import org.apache.reef.annotations.audience.DriverSide;
 import org.apache.reef.annotations.audience.Private;
+import org.apache.reef.driver.evaluator.EvaluatorProcess;
 import org.apache.reef.proto.ReefServiceProtos;
 import org.apache.reef.runtime.common.driver.api.ResourceLaunchEvent;
 import org.apache.reef.runtime.common.driver.api.ResourceReleaseEvent;
@@ -179,17 +180,27 @@ public final class ResourceManager {
       try (final LoggingScope lc = this.loggingScopeFactory
           
.getNewLoggingScope("ResourceManager.onResourceLaunchRequest:runCommand")) {
 
-        final List<String> command = launchRequest.getProcess()
-            
.setConfigurationFileName(this.fileNames.getEvaluatorConfigurationPath())
-            .setMemory((int) (this.jvmHeapFactor * c.getMemory()))
-            .getCommandLine();
-
+        final List<String> command = getLaunchCommand(launchRequest, 
c.getMemory());
         LOG.log(Level.FINEST, "Launching container: {0}", c);
         c.run(command);
       }
     }
   }
 
+  private List<String> getLaunchCommand(final ResourceLaunchEvent 
launchRequest,
+                                        final int containerMemory) {
+    final EvaluatorProcess process = launchRequest.getProcess()
+        
.setConfigurationFileName(this.fileNames.getEvaluatorConfigurationPath());
+
+    if (process.isOptionSet()) {
+      return process.getCommandLine();
+    } else {
+      return process
+          .setMemory((int) (this.jvmHeapFactor * containerMemory))
+          .getCommandLine();
+    }
+  }
+
   /**
   /**
    * Checks the allocation queue for new allocations and if there are any

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-runtime-mesos/src/main/java/org/apache/reef/runtime/mesos/driver/MesosResourceLaunchHandler.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-runtime-mesos/src/main/java/org/apache/reef/runtime/mesos/driver/MesosResourceLaunchHandler.java
 
b/lang/java/reef-runtime-mesos/src/main/java/org/apache/reef/runtime/mesos/driver/MesosResourceLaunchHandler.java
index 0ddba98..2aa413e 100644
--- 
a/lang/java/reef-runtime-mesos/src/main/java/org/apache/reef/runtime/mesos/driver/MesosResourceLaunchHandler.java
+++ 
b/lang/java/reef-runtime-mesos/src/main/java/org/apache/reef/runtime/mesos/driver/MesosResourceLaunchHandler.java
@@ -20,6 +20,7 @@ package org.apache.reef.runtime.mesos.driver;
 
 import org.apache.reef.annotations.audience.DriverSide;
 import org.apache.reef.annotations.audience.Private;
+import org.apache.reef.driver.evaluator.EvaluatorProcess;
 import org.apache.reef.io.TempFileCreator;
 import org.apache.reef.io.WorkingDirectoryTempFileCreator;
 import org.apache.reef.runtime.common.driver.api.ResourceLaunchEvent;
@@ -98,15 +99,26 @@ final class MesosResourceLaunchHandler implements 
ResourceLaunchHandler {
       FileUtil.copy(localStagingFolder, fileSystem, hdfsFolder, false, new 
org.apache.hadoop.conf.Configuration());
 
       // TODO: Replace REEFExecutor with a simple launch command (we only need 
to launch REEFExecutor)
-      final List<String> command = resourceLaunchEvent.getProcess()
-          
.setConfigurationFileName(this.fileNames.getEvaluatorConfigurationPath())
-          .setMemory((int) (this.jvmHeapFactor * 
this.executors.getMemory(resourceLaunchEvent.getIdentifier())))
-          .getCommandLine();
-
+      final List<String> command =
+          getLaunchCommand(resourceLaunchEvent, 
this.executors.getMemory(resourceLaunchEvent.getIdentifier()));
       this.executors.launchEvaluator(
           new EvaluatorLaunch(resourceLaunchEvent.getIdentifier(), 
StringUtils.join(command, ' ')));
     } catch (final IOException e) {
       throw new RuntimeException(e);
     }
   }
+
+  private List<String> getLaunchCommand(final ResourceLaunchEvent 
resourceLaunchEvent,
+                                        final int executorMemory) {
+    final EvaluatorProcess process = resourceLaunchEvent.getProcess()
+        
.setConfigurationFileName(this.fileNames.getEvaluatorConfigurationPath());
+
+    if (process.isOptionSet()) {
+      return process.getCommandLine();
+    } else {
+      return process
+          .setMemory((int) (this.jvmHeapFactor * executorMemory))
+          .getCommandLine();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/1da62700/lang/java/reef-runtime-yarn/src/main/java/org/apache/reef/runtime/yarn/driver/YARNResourceLaunchHandler.java
----------------------------------------------------------------------
diff --git 
a/lang/java/reef-runtime-yarn/src/main/java/org/apache/reef/runtime/yarn/driver/YARNResourceLaunchHandler.java
 
b/lang/java/reef-runtime-yarn/src/main/java/org/apache/reef/runtime/yarn/driver/YARNResourceLaunchHandler.java
index 5dd84c9..551ef34 100644
--- 
a/lang/java/reef-runtime-yarn/src/main/java/org/apache/reef/runtime/yarn/driver/YARNResourceLaunchHandler.java
+++ 
b/lang/java/reef-runtime-yarn/src/main/java/org/apache/reef/runtime/yarn/driver/YARNResourceLaunchHandler.java
@@ -23,6 +23,7 @@ import org.apache.hadoop.yarn.api.ApplicationConstants;
 import org.apache.hadoop.yarn.api.records.Container;
 import org.apache.hadoop.yarn.api.records.ContainerLaunchContext;
 import org.apache.hadoop.yarn.api.records.LocalResource;
+import org.apache.reef.driver.evaluator.EvaluatorProcess;
 import org.apache.reef.runtime.common.driver.api.ResourceLaunchEvent;
 import org.apache.reef.runtime.common.driver.api.ResourceLaunchHandler;
 import org.apache.reef.runtime.common.files.REEFFileNames;
@@ -76,15 +77,7 @@ public final class YARNResourceLaunchHandler implements 
ResourceLaunchHandler {
       final Map<String, LocalResource> localResources =
           this.evaluatorSetupHelper.getResources(resourceLaunchEvent);
 
-      final List<String> command = resourceLaunchEvent.getProcess()
-          
.setConfigurationFileName(this.filenames.getEvaluatorConfigurationPath())
-          .setMemory((int) (this.jvmHeapFactor * 
container.getResource().getMemory()))
-          .setStandardErr(ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/" +
-              this.filenames.getEvaluatorStderrFileName())
-          .setStandardOut(ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/" +
-              this.filenames.getEvaluatorStdoutFileName())
-          .getCommandLine();
-
+      final List<String> command = getLaunchCommand(resourceLaunchEvent, 
container.getResource().getMemory());
       if (LOG.isLoggable(Level.FINEST)) {
         LOG.log(Level.FINEST,
             "TIME: Run ResourceLaunchProto {0} command: `{1}` with resources: 
`{2}`",
@@ -101,4 +94,22 @@ public final class YARNResourceLaunchHandler implements 
ResourceLaunchHandler {
       throw new RuntimeException(e);
     }
   }
+
+  private List<String> getLaunchCommand(final ResourceLaunchEvent 
resourceLaunchEvent,
+                                        final int containerMemory) {
+    final EvaluatorProcess process = resourceLaunchEvent.getProcess()
+        
.setConfigurationFileName(this.filenames.getEvaluatorConfigurationPath())
+        .setStandardErr(ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/" +
+            this.filenames.getEvaluatorStderrFileName())
+        .setStandardOut(ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/" +
+            this.filenames.getEvaluatorStdoutFileName());
+
+    if (process.isOptionSet()) {
+      return process.getCommandLine();
+    } else {
+      return process
+          .setMemory((int) (this.jvmHeapFactor * containerMemory))
+          .getCommandLine();
+    }
+  }
 }


Reply via email to