Repository: oozie Updated Branches: refs/heads/master eed805ec3 -> d77b0d8a7
OOZIE-1794 java-opts and java-opt in the Java action don't always work properly in YARN (rkanter) Project: http://git-wip-us.apache.org/repos/asf/oozie/repo Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/d77b0d8a Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/d77b0d8a Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/d77b0d8a Branch: refs/heads/master Commit: d77b0d8a768508bd165763e7b132fa4cff5fe260 Parents: eed805e Author: Robert Kanter <[email protected]> Authored: Thu Apr 24 12:05:05 2014 -0700 Committer: Robert Kanter <[email protected]> Committed: Thu Apr 24 12:05:05 2014 -0700 ---------------------------------------------------------------------- .../oozie/action/hadoop/JavaActionExecutor.java | 38 +++--- .../action/hadoop/TestJavaActionExecutor.java | 121 +++++++++++++++++-- .../src/site/twiki/WorkflowFunctionalSpec.twiki | 18 ++- 3 files changed, 140 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/oozie/blob/d77b0d8a/core/src/main/java/org/apache/oozie/action/hadoop/JavaActionExecutor.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/action/hadoop/JavaActionExecutor.java b/core/src/main/java/org/apache/oozie/action/hadoop/JavaActionExecutor.java index 6fcdf2a..59ad143 100644 --- a/core/src/main/java/org/apache/oozie/action/hadoop/JavaActionExecutor.java +++ b/core/src/main/java/org/apache/oozie/action/hadoop/JavaActionExecutor.java @@ -280,13 +280,10 @@ public class JavaActionExecutor extends ActionExecutor { } launcherConf.setInt(YARN_AM_RESOURCE_MB, memoryMB); - // child.java.opts - String launcherMapOpts = launcherConf.get(HADOOP_MAP_JAVA_OPTS); - if (launcherMapOpts == null) { - launcherMapOpts = launcherConf.get(HADOOP_CHILD_JAVA_OPTS); - } + // We already made mapred.child.java.opts and mapreduce.map.java.opts equal, so just start with one of them + String launcherMapOpts = launcherConf.get(HADOOP_MAP_JAVA_OPTS, ""); String amChildOpts = launcherConf.get(YARN_AM_COMMAND_OPTS); - StringBuffer optsStr = new StringBuffer(); + StringBuilder optsStr = new StringBuilder(); int heapSizeForMap = extractHeapSizeMB(launcherMapOpts); int heapSizeForAm = extractHeapSizeMB(amChildOpts); int heapSize = Math.max(heapSizeForMap, heapSizeForAm) + YARN_MEMORY_MB_MIN; @@ -297,16 +294,12 @@ public class JavaActionExecutor extends ActionExecutor { if (amChildOpts != null) { optsStr.append(amChildOpts); } - if (launcherMapOpts != null) { - optsStr.append(" "); - optsStr.append(launcherMapOpts); - } + optsStr.append(" ").append(launcherMapOpts.trim()); if (heapSize > 0) { // append calculated total heap size to the end - optsStr.append(" "); - optsStr.append("-Xmx" + heapSize + "m"); + optsStr.append(" ").append("-Xmx").append(heapSize).append("m"); } - launcherConf.set(YARN_AM_COMMAND_OPTS, optsStr.toString()); + launcherConf.set(YARN_AM_COMMAND_OPTS, optsStr.toString().trim()); // child.env String launcherMapEnv = launcherConf.get(HADOOP_MAP_JAVA_ENV); @@ -759,21 +752,22 @@ public class JavaActionExecutor extends ActionExecutor { } LauncherMapperHelper.setupMainArguments(launcherJobConf, args); + // Make mapred.child.java.opts and mapreduce.map.java.opts equal, but give values from the latter priority; also append + // <java-opt> and <java-opts> and give those highest priority + StringBuilder opts = new StringBuilder(launcherJobConf.get(HADOOP_CHILD_JAVA_OPTS, "")); + if (launcherJobConf.get(HADOOP_MAP_JAVA_OPTS) != null) { + opts.append(" ").append(launcherJobConf.get(HADOOP_MAP_JAVA_OPTS)); + } List<Element> javaopts = actionXml.getChildren("java-opt", ns); for (Element opt: javaopts) { - String opts = launcherJobConf.get("mapred.child.java.opts", ""); - opts = opts + " " + opt.getTextTrim(); - opts = opts.trim(); - launcherJobConf.set("mapred.child.java.opts", opts); + opts.append(" ").append(opt.getTextTrim()); } - Element opt = actionXml.getChild("java-opts", ns); if (opt != null) { - String opts = launcherJobConf.get("mapred.child.java.opts", ""); - opts = opts + " " + opt.getTextTrim(); - opts = opts.trim(); - launcherJobConf.set("mapred.child.java.opts", opts); + opts.append(" ").append(opt.getTextTrim()); } + launcherJobConf.set(HADOOP_CHILD_JAVA_OPTS, opts.toString().trim()); + launcherJobConf.set(HADOOP_MAP_JAVA_OPTS, opts.toString().trim()); // setting for uber mode if (launcherJobConf.getBoolean(HADOOP_YARN_UBER_MODE, false)) { http://git-wip-us.apache.org/repos/asf/oozie/blob/d77b0d8a/core/src/test/java/org/apache/oozie/action/hadoop/TestJavaActionExecutor.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/action/hadoop/TestJavaActionExecutor.java b/core/src/test/java/org/apache/oozie/action/hadoop/TestJavaActionExecutor.java index 62c57a8..390ad3f 100644 --- a/core/src/test/java/org/apache/oozie/action/hadoop/TestJavaActionExecutor.java +++ b/core/src/test/java/org/apache/oozie/action/hadoop/TestJavaActionExecutor.java @@ -242,6 +242,7 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { assertEquals("MAIN-CLASS", actionConf.get("oozie.action.java.main", "null")); assertEquals("org.apache.oozie.action.hadoop.JavaMain", ae.getLauncherMain(conf, actionXml)); assertTrue(conf.get("mapred.child.java.opts").contains("JAVA-OPTS")); + assertTrue(conf.get("mapreduce.map.java.opts").contains("JAVA-OPTS")); assertEquals(Arrays.asList("A1", "A2"), Arrays.asList(LauncherMapper.getMainArguments(conf))); assertTrue(getFileSystem().exists(new Path(context.getActionDir(), LauncherMapper.ACTION_CONF_XML))); @@ -1061,8 +1062,8 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { Configuration conf = ae.createLauncherConf(getFileSystem(), context, action, actionXmlconf, actionConf); - assertTrue(conf.get("mapred.child.java.opts").contains("JAVA-OPT1")); - assertTrue(conf.get("mapred.child.java.opts").contains("JAVA-OPT2")); + assertEquals("-Xmx200m JAVA-OPT1 JAVA-OPT2", conf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m JAVA-OPT1 JAVA-OPT2", conf.get("mapreduce.map.java.opts")); actionXml = "<java>" + "<job-tracker>" + getJobTrackerUri() + "</job-tracker>" + "<name-node>" + getNameNodeUri() + "</name-node>" + "<job-xml>job.xml</job-xml>" + "<job-xml>job2.xml</job-xml>" @@ -1086,8 +1087,90 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { conf = ae.createLauncherConf(getFileSystem(), context, action, actionXmlconf, actionConf); - assertTrue(conf.get("mapred.child.java.opts").contains("JAVA-OPT1")); - assertTrue(conf.get("mapred.child.java.opts").contains("JAVA-OPT2")); + assertEquals("-Xmx200m JAVA-OPT1 JAVA-OPT2", conf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m JAVA-OPT1 JAVA-OPT2", conf.get("mapreduce.map.java.opts")); + + actionXml = "<java>" + "<job-tracker>" + getJobTrackerUri() + "</job-tracker>" + "<name-node>" + + getNameNodeUri() + "</name-node>" + "<job-xml>job.xml</job-xml>" + "<job-xml>job2.xml</job-xml>" + + "<configuration>" + "<property><name>oozie.launcher.a</name><value>LA</value></property>" + + "<property><name>a</name><value>AA</value></property>" + + "<property><name>b</name><value>BB</value></property>" + + "<property><name>oozie.launcher.mapred.child.java.opts</name><value>JAVA-OPT3</value></property>" + + "</configuration>" + + "<main-class>MAIN-CLASS</main-class>" + "<java-opt>JAVA-OPT1</java-opt>" + + "<java-opt>JAVA-OPT2</java-opt>" + "<arg>A1</arg>" + "<arg>A2</arg>" + "<file>f.jar</file>" + + "<archive>a.tar</archive>" + "</java>"; + + wfBean = addRecordToWfJobTable("test1", actionXml); + action = (WorkflowActionBean) wfBean.getActions().get(0); + action.setType(ae.getType()); + action.setConf(actionXml); + + context = new Context(wfBean, action); + + actionXmlconf = XmlUtils.parseXml(action.getConf()); + + actionConf = ae.createBaseHadoopConf(context, actionXmlconf); + + conf = ae.createLauncherConf(getFileSystem(), context, action, actionXmlconf, actionConf); + + assertEquals("JAVA-OPT3 JAVA-OPT1 JAVA-OPT2", conf.get("mapred.child.java.opts")); + assertEquals("JAVA-OPT3 JAVA-OPT1 JAVA-OPT2", conf.get("mapreduce.map.java.opts")); + + actionXml = "<java>" + "<job-tracker>" + getJobTrackerUri() + "</job-tracker>" + "<name-node>" + + getNameNodeUri() + "</name-node>" + "<job-xml>job.xml</job-xml>" + "<job-xml>job2.xml</job-xml>" + + "<configuration>" + "<property><name>oozie.launcher.a</name><value>LA</value></property>" + + "<property><name>a</name><value>AA</value></property>" + + "<property><name>b</name><value>BB</value></property>" + + "<property><name>oozie.launcher.mapreduce.map.java.opts</name><value>JAVA-OPT3</value></property>" + + "</configuration>" + + "<main-class>MAIN-CLASS</main-class>" + "<java-opt>JAVA-OPT1</java-opt>" + + "<java-opt>JAVA-OPT2</java-opt>" + "<arg>A1</arg>" + "<arg>A2</arg>" + "<file>f.jar</file>" + + "<archive>a.tar</archive>" + "</java>"; + + wfBean = addRecordToWfJobTable("test1", actionXml); + action = (WorkflowActionBean) wfBean.getActions().get(0); + action.setType(ae.getType()); + action.setConf(actionXml); + + context = new Context(wfBean, action); + + actionXmlconf = XmlUtils.parseXml(action.getConf()); + + actionConf = ae.createBaseHadoopConf(context, actionXmlconf); + + conf = ae.createLauncherConf(getFileSystem(), context, action, actionXmlconf, actionConf); + + assertEquals("-Xmx200m JAVA-OPT3 JAVA-OPT1 JAVA-OPT2", conf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m JAVA-OPT3 JAVA-OPT1 JAVA-OPT2", conf.get("mapreduce.map.java.opts")); + + actionXml = "<java>" + "<job-tracker>" + getJobTrackerUri() + "</job-tracker>" + "<name-node>" + + getNameNodeUri() + "</name-node>" + "<job-xml>job.xml</job-xml>" + "<job-xml>job2.xml</job-xml>" + + "<configuration>" + "<property><name>oozie.launcher.a</name><value>LA</value></property>" + + "<property><name>a</name><value>AA</value></property>" + + "<property><name>b</name><value>BB</value></property>" + + "<property><name>oozie.launcher.mapred.child.java.opts</name><value>JAVA-OPT3</value></property>" + + "<property><name>oozie.launcher.mapreduce.map.java.opts</name><value>JAVA-OPT4</value></property>" + + "</configuration>" + + "<main-class>MAIN-CLASS</main-class>" + "<java-opt>JAVA-OPT1</java-opt>" + + "<java-opt>JAVA-OPT2</java-opt>" + "<arg>A1</arg>" + "<arg>A2</arg>" + "<file>f.jar</file>" + + "<archive>a.tar</archive>" + "</java>"; + + wfBean = addRecordToWfJobTable("test1", actionXml); + action = (WorkflowActionBean) wfBean.getActions().get(0); + action.setType(ae.getType()); + action.setConf(actionXml); + + context = new Context(wfBean, action); + + actionXmlconf = XmlUtils.parseXml(action.getConf()); + + actionConf = ae.createBaseHadoopConf(context, actionXmlconf); + + conf = ae.createLauncherConf(getFileSystem(), context, action, actionXmlconf, actionConf); + + assertEquals("JAVA-OPT3 JAVA-OPT4 JAVA-OPT1 JAVA-OPT2", conf.get("mapred.child.java.opts")); + assertEquals("JAVA-OPT3 JAVA-OPT4 JAVA-OPT1 JAVA-OPT2", conf.get("mapreduce.map.java.opts")); } public void testActionLibsPath() throws Exception { @@ -1624,6 +1707,8 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { assertEquals("2560", launcherConf.get(JavaActionExecutor.YARN_AM_RESOURCE_MB)); // heap size in child.opts (2048 + 512) int heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); + assertEquals("-Xmx2048m -Djava.net.preferIPv4Stack=true", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx2048m -Djava.net.preferIPv4Stack=true", launcherConf.get("mapreduce.map.java.opts")); // There's an extra parameter (-Xmx1024m) in here when using YARN that's not here when using MR1 if (createJobConf().get("yarn.resourcemanager.address") != null) { assertEquals("-Xmx1024m -Xmx2048m -Djava.net.preferIPv4Stack=true -Xmx2560m", @@ -1633,6 +1718,7 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { assertEquals("-Xmx2048m -Djava.net.preferIPv4Stack=true -Xmx2560m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); } + assertEquals(2560, heapSize); // env assertEquals("A=foo", launcherConf.get(JavaActionExecutor.YARN_AM_ENV)); @@ -1664,7 +1750,9 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { // heap size (2560 + 512) heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); - assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx2560m -XX:NewRatio=8 -Xmx3072m", + assertEquals("-Xmx1536m -Xmx2560m -XX:NewRatio=8", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx1536m -Xmx2560m -XX:NewRatio=8", launcherConf.get("mapreduce.map.java.opts")); + assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx1536m -Xmx2560m -XX:NewRatio=8 -Xmx3072m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); assertEquals(3072, heapSize); @@ -1700,8 +1788,11 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { // heap size (limit to 3584) heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); - assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx4000m -XX:NewRatio=8 -Xmx3584m", + assertEquals("-Xmx1536m -Xmx4000m -XX:NewRatio=8", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx1536m -Xmx4000m -XX:NewRatio=8", launcherConf.get("mapreduce.map.java.opts")); + assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx1536m -Xmx4000m -XX:NewRatio=8 -Xmx3584m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); + assertEquals(3584, heapSize); // env (equqls to mapreduce.map.env + am.env) assertEquals("A=foo,B=bar", launcherConf.get(JavaActionExecutor.YARN_AM_ENV)); @@ -1721,7 +1812,7 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { + "<configuration>" + "<property><name>oozie.launcher.yarn.app.mapreduce.am.command-opts</name>" + "<value>-Xmx1024m -Djava.net.preferIPv4Stack=true </value></property>" - + "<property><name>oozie.launcher.mapred.child.java.opts</name><value>-Xmx1536m</value></property>" + + "<property><name>oozie.launcher.mapreduce.map.java.opts</name><value>-Xmx1536m</value></property>" + "</configuration>" + "<main-class>MAIN-CLASS</main-class>" + "<java-opt>-Xmx2048m</java-opt>" + "<java-opt>-Dkey1=val1</java-opt>" @@ -1741,7 +1832,9 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { // heap size (2048 + 512) int heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); - assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx1536m -Xmx2048m -Dkey1=val1 -Dkey2=val2 -Xmx2560m", + assertEquals("-Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1 -Dkey2=val2", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1 -Dkey2=val2", launcherConf.get("mapreduce.map.java.opts")); + assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1 -Dkey2=val2 -Xmx2560m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); assertEquals(2560, heapSize); @@ -1756,7 +1849,7 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { + "<configuration>" + "<property><name>oozie.launcher.yarn.app.mapreduce.am.command-opts</name>" + "<value>-Xmx1024m -Djava.net.preferIPv4Stack=true </value></property>" - + "<property><name>oozie.launcher.mapred.child.java.opts</name><value>-Xmx1536m</value></property>" + + "<property><name>oozie.launcher.mapreduce.map.java.opts</name><value>-Xmx1536m</value></property>" + "</configuration>" + "<main-class>MAIN-CLASS</main-class>" + "<java-opts>-Xmx2048m -Dkey1=val1</java-opts>" + "</java>"); @@ -1765,7 +1858,9 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { // heap size (2048 + 512) heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); - assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx1536m -Xmx2048m -Dkey1=val1 -Xmx2560m", + assertEquals("-Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1", launcherConf.get("mapreduce.map.java.opts")); + assertEquals("-Xmx1024m -Djava.net.preferIPv4Stack=true -Xmx200m -Xmx1536m -Xmx2048m -Dkey1=val1 -Xmx2560m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); assertEquals(2560, heapSize); @@ -1780,7 +1875,7 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { + "<configuration>" + "<property><name>oozie.launcher.yarn.app.mapreduce.am.command-opts</name>" + "<value>-Xmx2048m -Djava.net.preferIPv4Stack=true </value></property>" - + "<property><name>oozie.launcher.mapred.child.java.opts</name><value>-Xmx3072m</value></property>" + + "<property><name>oozie.launcher.mapreduce.map.java.opts</name><value>-Xmx3072m</value></property>" + "</configuration>" + "<main-class>MAIN-CLASS</main-class>" + "<java-opts>-Xmx1024m -Dkey1=val1</java-opts>" + "</java>"); @@ -1789,7 +1884,9 @@ public class TestJavaActionExecutor extends ActionExecutorTestCase { // heap size (2048 + 512) heapSize = ae.extractHeapSizeMB(launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS)); - assertEquals("-Xmx2048m -Djava.net.preferIPv4Stack=true -Xmx3072m -Xmx1024m -Dkey1=val1 -Xmx2560m", + assertEquals("-Xmx200m -Xmx3072m -Xmx1024m -Dkey1=val1", launcherConf.get("mapred.child.java.opts")); + assertEquals("-Xmx200m -Xmx3072m -Xmx1024m -Dkey1=val1", launcherConf.get("mapreduce.map.java.opts")); + assertEquals("-Xmx2048m -Djava.net.preferIPv4Stack=true -Xmx200m -Xmx3072m -Xmx1024m -Dkey1=val1 -Xmx2560m", launcherConf.get(JavaActionExecutor.YARN_AM_COMMAND_OPTS).trim()); assertEquals(2560, heapSize); } http://git-wip-us.apache.org/repos/asf/oozie/blob/d77b0d8a/docs/src/site/twiki/WorkflowFunctionalSpec.twiki ---------------------------------------------------------------------- diff --git a/docs/src/site/twiki/WorkflowFunctionalSpec.twiki b/docs/src/site/twiki/WorkflowFunctionalSpec.twiki index 40dcd1f..f7590d0 100644 --- a/docs/src/site/twiki/WorkflowFunctionalSpec.twiki +++ b/docs/src/site/twiki/WorkflowFunctionalSpec.twiki @@ -1421,9 +1421,21 @@ hcat://[metastore server]:[port]/[database name]/[table name]/[partkey1]=[value] In case of a hcatalog URI, the hive-site.xml needs to be shipped using =file= tag and the hcatalog and hive jars need to be placed in workflow lib directory or specified using =archive= tag. -The =java-opts= element, if present, contains the command line parameters which are to be used to start the JVM that -will execute the Java application. Using this element is equivalent to use the =mapred.child.java.opts= configuration -property. +The =java-opts= and =java-opt= elements, if present, contains the command line parameters which are to be used to start the JVM that +will execute the Java application. Using this element is equivalent to using the =mapred.child.java.opts= +or =mapreduce.map.java.opts= configuration properties, with the advantage that Oozie will append to these properties instead of +simply setting them (e.g. if you have one of these properties specified in mapred-site.xml, setting it again in +the =configuration= element will override it, but using =java-opts= or =java-opt= will instead append to it, preserving the original +value). You can have either one =java-opts=, multiple =java-opt=, or neither; you cannot use both at the same time. In any case, +Oozie will set both =mapred.child.java.opts= and =mapreduce.map.java.opts= to the same value based on combining them. In other +words, after Oozie is finished: +<verbatim> +mapred.child.java.opts <-- "<mapred.child.java.opts> <mapreduce.map.java.opts> <java-opt...|java-opts>" +mapreduce.map.java.opts <-- "<mapred.child.java.opts> <mapreduce.map.java.opts> <java-opt...|java-opts>" +</verbatim> +In the case that parameters are repeated, the latest instance of the parameter is used by Java. This means that =java-opt= +(or =java-opts=) has the highest priority, followed by =mapreduce.map.java.opts=, and finally =mapred.child.java.opts=. When +multiple =java-opt= are specified, they are included from top to bottom ordering, where the bottom has highest priority. The =arg= elements, if present, contains arguments for the main function. The value of each =arg= element is considered a single argument and they are passed to the =main= method in the same order.
