jmeter5.6.3源码解析

JMeter是一款开源的Java应用,用于进行性能测试和功能测试。它允许用户创建测试计划,模拟多个用户并发地访问应用程序,以测量应用程序的性能。JMeter的源码结构相当复杂,但以下是对其核心部分的简要解析:

1.入口类:NewDriver

  • NewDriver是整个JMeter的入口类,它的主要任务是启动JMeter测试。
  • 该类包含了一些静态方法,如jar包的扫描、命令解析、全局参数定义以及类加载器路径操作等。
  • 最重要的是它的main方法,该方法通过反射调用JMeter类,并启动其start方法。根据传入的参数,main方法会判断执行GUI模式还是NON_GUI模式。官方日志特别强调,若要执行发压工作,应使用命令行模式,因为这会影响发压效率和资源消耗。
    /*
     * 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.jmeter;
    
    // N.B. this must only use standard Java packages
    
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.lang.reflect.Method;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.format.DateTimeFormatter;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.StringTokenizer;
    
    /**
     * Main class for JMeter - sets up initial classpath and the loader.
     *
     */
    public final class NewDriver {
    
        private static final String CLASSPATH_SEPARATOR = File.pathSeparator;
    
        private static final String OS_NAME = System.getProperty("os.name");// $NON-NLS-1$
    
        private static final String OS_NAME_LC = OS_NAME.toLowerCase(java.util.Locale.ENGLISH);
    
        private static final String JAVA_CLASS_PATH = "java.class.path";// $NON-NLS-1$
    
        private static final String JMETER_LOGFILE_SYSTEM_PROPERTY = "jmeter.logfile";// $NON-NLS-1$
    
        private static final String HEADLESS_MODE_PROPERTY = "java.awt.headless";// $NON-NLS-1$
        /** The class loader to use for loading JMeter classes. */
        private static final DynamicClassLoader loader;
    
        /** The directory JMeter is installed in. */
        private static final String JMETER_INSTALLATION_DIRECTORY;
    
        private static final List<Exception> EXCEPTIONS_IN_INIT = new ArrayList<>();
    
        static {
            final List<URL> jars = new ArrayList<>();
            final String initiaClasspath = System.getProperty(JAVA_CLASS_PATH);
    
            // Find JMeter home dir from the initial classpath
            String tmpDir;
            StringTokenizer tok = new StringTokenizer(initiaClasspath, File.pathSeparator);
            if (tok.countTokens() == 1
                    || (tok.countTokens()  == 2 // Java on Mac OS can add a second entry to the initial classpath
                        && OS_NAME_LC.startsWith("mac os x")// $NON-NLS-1$
                       )
               ) {
                File jar = new File(tok.nextToken());
                try {
                    tmpDir = jar.getCanonicalFile().getParentFile().getParent();
                } catch (IOException e) {
                    tmpDir = null;
                }
            } else {// e.g. started from IDE with full classpath
                tmpDir = System.getProperty("jmeter.home", System.getenv("JMETER_HOME"));// Allow override $NON-NLS-1$ $NON-NLS-2$
                if (tmpDir == null || tmpDir.length() == 0) {
                    File userDir = new File(System.getProperty("user.dir"));// $NON-NLS-1$
                    tmpDir = userDir.getAbsoluteFile().getParent();
                }
            }
            if (tmpDir == null) {
                tmpDir = System.getenv("JMETER_HOME");
            }
            JMETER_INSTALLATION_DIRECTORY=tmpDir;
    
            /*
             * Does the system support UNC paths? If so, may need to fix them up
             * later
             */
            boolean usesUNC = OS_NAME_LC.startsWith("windows");// $NON-NLS-1$
    
            // Add standard jar locations to initial classpath
            StringBuilder classpath = new StringBuilder();
            File[] libDirs = new File[] { new File(JMETER_INSTALLATION_DIRECTORY + File.separator + "lib"),// $NON-NLS-1$ $NON-NLS-2$
                    new File(JMETER_INSTALLATION_DIRECTORY + File.separator + "lib" + File.separator + "ext"),// $NON-NLS-1$ $NON-NLS-2$
                    new File(JMETER_INSTALLATION_DIRECTORY + File.separator + "lib" + File.separator + "junit")};// $NON-NLS-1$ $NON-NLS-2$
            for (File libDir : libDirs) {
                File[] libJars = libDir.listFiles((dir, name) -> name.endsWith(".jar"));
                if (libJars == null) {
                    new Throwable("Could not access " + libDir).printStackTrace(); // NOSONAR No logging here
                    continue;
                }
                Arrays.sort(libJars); // Bug 50708 Ensure predictable order of jars
                for (File libJar : libJars) {
                    try {
                        String s = libJar.getPath();
    
                        // Fix path to allow the use of UNC URLs
                        if (usesUNC) {
                            if (s.startsWith("\\\\") && !s.startsWith("\\\\\\")) {// $NON-NLS-1$ $NON-NLS-2$
                                s = "\\\\" + s;// $NON-NLS-1$
                            } else if (s.startsWith("//") && !s.startsWith("///")) {// $NON-NLS-1$ $NON-NLS-2$
                                s = "//" + s;// $NON-NLS-1$
                            }
                        } // usesUNC
    
                        jars.add(new File(s).toURI().toURL());// See Java bug 4496398
                        classpath.append(CLASSPATH_SEPARATOR);
                        classpath.append(s);
                    } catch (MalformedURLException e) { // NOSONAR
                        EXCEPTIONS_IN_INIT.add(new Exception("Error adding jar:"+libJar.getAbsolutePath(), e));
                    }
                }
            }
    
            // ClassFinder needs the classpath
            System.setProperty(JAVA_CLASS_PATH, initiaClasspath + classpath.toString());
            loader = createClassLoader(jars);
        }
    
        @SuppressWarnings("removal")
        private static DynamicClassLoader createClassLoader(List<URL> jars) {
            return java.security.AccessController.doPrivileged(
                    (java.security.PrivilegedAction<DynamicClassLoader>) () ->
                            new DynamicClassLoader(jars.toArray(new URL[jars.size()]))
            );
        }
    
        /**
         * Prevent instantiation.
         */
        private NewDriver() {
        }
    
        /**
         * Generate an array of jar files located in a directory.
         * Jar files located in sub directories will not be added.
         *
         * @param dir to search for the jar files.
         */
        private static File[] listJars(File dir) {
            if (dir.isDirectory()) {
                return dir.listFiles((f, name) -> {
                    if (name.endsWith(".jar")) {// $NON-NLS-1$
                        File jar = new File(f, name);
                        return jar.isFile() && jar.canRead();
                    }
                    return false;
                });
            }
            return new File[0];
        }
    
        /**
         * Add a URL to the loader classpath only; does not update the system classpath.
         *
         * @param path to be added.
         * @throws MalformedURLException when <code>path</code> points to an invalid url
         */
        public static void addURL(String path) throws MalformedURLException {
            File furl = new File(path);
            loader.addURL(furl.toURI().toURL()); // See Java bug 4496398
            File[] jars = listJars(furl);
            for (File jar : jars) {
                loader.addURL(jar.toURI().toURL()); // See Java bug 4496398
            }
        }
    
        /**
         * Add a URL to the loader classpath only; does not update the system
         * classpath.
         *
         * @param url
         *            The {@link URL} to add to the classpath
         */
        public static void addURL(URL url) {
            loader.addURL(url);
        }
    
        /**
         * Add a directory or jar to the loader and system classpaths.
         *
         * @param path
         *            to add to the loader and system classpath
         * @throws MalformedURLException
         *             if <code>path</code> can not be transformed to a valid
         *             {@link URL}
         */
        public static void addPath(String path) throws MalformedURLException {
            File file = new File(path);
            // Ensure that directory URLs end in "/"
            if (file.isDirectory() && !path.endsWith("/")) {// $NON-NLS-1$
                file = new File(path + "/");// $NON-NLS-1$
            }
            loader.addURL(file.toURI().toURL()); // See Java bug 4496398
            StringBuilder sb = new StringBuilder(System.getProperty(JAVA_CLASS_PATH));
            sb.append(CLASSPATH_SEPARATOR);
            sb.append(path);
            File[] jars = listJars(file);
            for (File jar : jars) {
                loader.addURL(jar.toURI().toURL()); // See Java bug 4496398
                sb.append(CLASSPATH_SEPARATOR);
                sb.append(jar.getPath());
            }
    
            // ClassFinder needs this
            System.setProperty(JAVA_CLASS_PATH,sb.toString());
        }
    
        /**
         * Get the directory where JMeter is installed. This is the absolute path
         * name.
         *
         * @return the directory where JMeter is installed.
         */
        public static String getJMeterDir() {
            return JMETER_INSTALLATION_DIRECTORY;
        }
    
        /**
         * The main program which actually runs JMeter.
         *
         * @param args
         *            the command line arguments
         */
        public static void main(String[] args) {
            if(!EXCEPTIONS_IN_INIT.isEmpty()) {
                System.err.println("Configuration error during init, see exceptions:"+exceptionsToString(EXCEPTIONS_IN_INIT)); // NOSONAR Intentional System.err use
            } else {
                Thread.currentThread().setContextClassLoader(loader);
    
    
                setLoggingProperties(args);
    
                try {
                    // Only set property if it has not been set explicitely
                    if(System.getProperty(HEADLESS_MODE_PROPERTY) == null && shouldBeHeadless(args)) {
                        System.setProperty(HEADLESS_MODE_PROPERTY, "true");
                    }
                    Class<?> initialClass = loader.loadClass("org.apache.jmeter.JMeter");// $NON-NLS-1$
                    Object instance = initialClass.getDeclaredConstructor().newInstance();
                    Method startup = initialClass.getMethod("start", new Class[] { new String[0].getClass() });// $NON-NLS-1$
                    startup.invoke(instance, new Object[] { args });
                } catch(Throwable e){ // NOSONAR We want to log home directory in case of exception
                    e.printStackTrace(); // NOSONAR No logger at this step
                    System.err.println("JMeter home directory was detected as: "+JMETER_INSTALLATION_DIRECTORY); // NOSONAR Intentional System.err use
                }
            }
        }
    
        /**
         * @param exceptionsInInit List of {@link Exception}
         * @return String
         */
        private static String exceptionsToString(List<? extends Exception> exceptionsInInit) {
            StringBuilder builder = new StringBuilder();
            for (Exception exception : exceptionsInInit) {
                StringWriter stringWriter = new StringWriter();
                PrintWriter printWriter = new PrintWriter(stringWriter);
                exception.printStackTrace(printWriter); // NOSONAR
                builder.append(stringWriter.toString())
                    .append("\r\n");
            }
            return builder.toString();
        }
    
        /*
         * Set logging related system properties.
         */
        private static void setLoggingProperties(String[] args) {
            String jmLogFile = getCommandLineArgument(args, 'j', "jmeterlogfile");// $NON-NLS-1$ $NON-NLS-2$
    
            if (jmLogFile != null && !jmLogFile.isEmpty()) {
                jmLogFile = replaceDateFormatInFileName(jmLogFile);
                System.setProperty(JMETER_LOGFILE_SYSTEM_PROPERTY, jmLogFile);// $NON-NLS-1$
            } else if (System.getProperty(JMETER_LOGFILE_SYSTEM_PROPERTY) == null) {// $NON-NLS-1$
                System.setProperty(JMETER_LOGFILE_SYSTEM_PROPERTY, "jmeter.log");// $NON-NLS-1$ $NON-NLS-2$
            }
    
            String jmLogConf = getCommandLineArgument(args, 'i', "jmeterlogconf");// $NON-NLS-1$ $NON-NLS-2$
            File logConfFile = null;
    
            if (jmLogConf != null && !jmLogConf.isEmpty()) {
                logConfFile = new File(jmLogConf);
            } else if (System.getProperty("log4j.configurationFile") == null) {// $NON-NLS-1$
                logConfFile = new File("log4j2.xml");// $NON-NLS-1$
                if (!logConfFile.isFile()) {
                    logConfFile = new File(JMETER_INSTALLATION_DIRECTORY, "bin" + File.separator + "log4j2.xml");// $NON-NLS-1$ $NON-NLS-2$
                }
            }
    
            if (logConfFile != null) {
                System.setProperty("log4j.configurationFile", logConfFile.toURI().toString());// $NON-NLS-1$
            }
        }
    
        private static boolean shouldBeHeadless(String[] args) {
            for (String arg : args) {
                if("-n".equals(arg) || "-s".equals(arg) || "-g".equals(arg)) {
                    return true;
                }
            }
            return false;
        }
        /*
         * Find command line argument option value by the id and name.
         */
        private static String getCommandLineArgument(String[] args, int id, String name) {
            final String shortArgName = "-" + ((char) id);// $NON-NLS-1$
            final String longArgName = "--" + name;// $NON-NLS-1$
    
            String value = null;
    
            for (int i = 0; i < args.length; i++) {
                if ((shortArgName.equals(args[i]) && i < args.length - 1)
                        || longArgName.equals(args[i])) {
                    if (!args[i + 1].startsWith("-")) {// $NON-NLS-1$
                        value = args[i + 1];
                    }
                    break;
                } else if (!shortArgName.equals(args[i]) && args[i].startsWith(shortArgName)) {
                    value = args[i].substring(shortArgName.length());
                    break;
                }
            }
    
            return value;
        }
    
        /*
         * If the fileName contains at least one set of paired single-quotes, reformat using DateFormat
         */
        private static String replaceDateFormatInFileName(String fileName) {
            try {
                StringBuilder builder = new StringBuilder();
    
                final Instant date = Instant.now();
                int fromIndex = 0;
                int begin = fileName.indexOf('\'', fromIndex);// $NON-NLS-1$
                int end;
    
                String format;
                DateTimeFormatter dateFormat;
    
                while (begin != -1) {
                    builder.append(fileName.substring(fromIndex, begin));
    
                    fromIndex = begin + 1;
                    end = fileName.indexOf('\'', fromIndex);// $NON-NLS-1$
                    if (end == -1) {
                        throw new IllegalArgumentException("Invalid pairs of single-quotes in the file name: " + fileName);// $NON-NLS-1$
                    }
    
                    format = fileName.substring(begin + 1, end);
                    dateFormat = DateTimeFormatter.ofPattern(format).withZone(ZoneId.systemDefault());
                    builder.append(dateFormat.format(date));
    
                    fromIndex = end + 1;
                    begin = fileName.indexOf('\'', fromIndex);// $NON-NLS-1$
                }
    
                if (fromIndex < fileName.length() - 1) {
                    builder.append(fileName.substring(fromIndex));
                }
    
                return builder.toString();
            } catch (Exception ex) {
                System.err.println("Error replacing date format in file name:"+fileName+", error:"+ex.getMessage()); // NOSONAR
            }
    
            return fileName;
        }
    }
    

2. 业务逻辑类:JMeter

  • JMeter类由NewDriver入口类通过反射调用,是实际的业务逻辑类。
  • 它负责接收用户的启动参数并进行解析。
  • 启动BeanShell服务。
  • JMeter类的start方法是其重点部分,因为它负责解析传入的指令,并对后续应用模式进行逻辑判断。如果未配置远程参数,启动类StandardJMeterEngine的runTest(); 如果已配置远程参数,启动远程类DistributedRunner的start(),此处最终仍然调用 StandardJMeterEngine的runTest();
  • /*
     * 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.jmeter;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Reader;
    import java.net.Authenticator;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.MalformedURLException;
    import java.net.SocketException;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.time.Instant;
    import java.time.ZoneId;
    import java.time.format.DateTimeFormatter;
    import java.time.format.FormatStyle;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Enumeration;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    import java.util.Properties;
    import java.util.StringTokenizer;
    import java.util.concurrent.ConcurrentLinkedQueue;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.atomic.AtomicInteger;
    import java.util.stream.Collectors;
    
    import javax.script.Bindings;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineFactory;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    import org.apache.commons.cli.avalon.CLArgsParser;
    import org.apache.commons.cli.avalon.CLOption;
    import org.apache.commons.cli.avalon.CLOptionDescriptor;
    import org.apache.commons.cli.avalon.CLUtil;
    import org.apache.commons.io.FilenameUtils;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.apache.jmeter.control.ReplaceableController;
    import org.apache.jmeter.engine.ClientJMeterEngine;
    import org.apache.jmeter.engine.DistributedRunner;
    import org.apache.jmeter.engine.JMeterEngine;
    import org.apache.jmeter.engine.RemoteJMeterEngineImpl;
    import org.apache.jmeter.engine.StandardJMeterEngine;
    import org.apache.jmeter.engine.TreeCloner;
    import org.apache.jmeter.exceptions.IllegalUserActionException;
    import org.apache.jmeter.gui.action.LoadRecentProject;
    import org.apache.jmeter.gui.tree.JMeterTreeModel;
    import org.apache.jmeter.gui.tree.JMeterTreeNode;
    import org.apache.jmeter.plugin.JMeterPlugin;
    import org.apache.jmeter.plugin.PluginManager;
    import org.apache.jmeter.report.config.ConfigurationException;
    import org.apache.jmeter.report.dashboard.ReportGenerator;
    import org.apache.jmeter.reporters.ResultCollector;
    import org.apache.jmeter.reporters.Summariser;
    import org.apache.jmeter.rmi.RmiUtils;
    import org.apache.jmeter.samplers.Remoteable;
    import org.apache.jmeter.samplers.SampleEvent;
    import org.apache.jmeter.save.SaveService;
    import org.apache.jmeter.services.FileServer;
    import org.apache.jmeter.testelement.TestElement;
    import org.apache.jmeter.testelement.TestElementSchema;
    import org.apache.jmeter.testelement.TestStateListener;
    import org.apache.jmeter.threads.RemoteThreadsListenerTestElement;
    import org.apache.jmeter.util.BeanShellInterpreter;
    import org.apache.jmeter.util.BeanShellServer;
    import org.apache.jmeter.util.JMeterUtils;
    import org.apache.jmeter.util.SecurityProviderLoader;
    import org.apache.jmeter.util.ShutdownClient;
    import org.apache.jorphan.collections.HashTree;
    import org.apache.jorphan.collections.SearchByClass;
    import org.apache.jorphan.reflect.ClassTools;
    import org.apache.jorphan.util.HeapDumper;
    import org.apache.jorphan.util.JMeterException;
    import org.apache.jorphan.util.JOrphanUtils;
    import org.apache.jorphan.util.ThreadDumper;
    import org.apache.logging.log4j.Level;
    import org.apache.logging.log4j.core.config.Configurator;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * Main JMeter class; processes options and starts the GUI, non-GUI or server as appropriate.
     */
    public class JMeter implements JMeterPlugin {
        private static final String JSR223_INIT_FILE = "jsr223.init.file";
    
        private static final Logger log = LoggerFactory.getLogger(JMeter.class);
    
        public static final int UDP_PORT_DEFAULT = ShutdownClient.UDP_PORT_DEFAULT;
    
        public static final String HTTP_PROXY_PASS = "http.proxyPass"; // $NON-NLS-1$
    
        public static final String HTTP_PROXY_USER = "http.proxyUser"; // $NON-NLS-1$
    
        public static final String JMETER_NON_GUI = "JMeter.NonGui"; // $NON-NLS-1$
    
        public static final String JMETER_REPORT_OUTPUT_DIR_PROPERTY =
                "jmeter.reportgenerator.outputdir"; //$NON-NLS-1$
    
        // Icons size in the JMeter tree
        public static final String TREE_ICON_SIZE = "jmeter.tree.icons.size"; //$NON-NLS-1$
    
        public static final String DEFAULT_TREE_ICON_SIZE = "19x19"; //$NON-NLS-1$
    
        protected static final String KEY_SIZE = "<SIZE>"; //$NON-NLS-1$
    
        // If the -t flag is to "LAST", then the last loaded file (if any) is used
        private static final String USE_LAST_JMX = "LAST";
        // If the -j  or -l flag is set to LAST or LAST.log|LAST.jtl, then the last loaded file name is used to
        // generate the log file name by removing .JMX and replacing it with .log|.jtl
    
        private static final int PROXY_PASSWORD     = 'a';// $NON-NLS-1$
        private static final int JMETER_HOME_OPT    = 'd';// $NON-NLS-1$
        private static final int HELP_OPT           = 'h';// $NON-NLS-1$
        private static final int OPTIONS_OPT        = '?';// $NON-NLS-1$
        // logging configuration file
        private static final int JMLOGCONF_OPT      = 'i';// $NON-NLS-1$
        // jmeter.log
        private static final int JMLOGFILE_OPT      = 'j';// $NON-NLS-1$
        // sample result log file
        private static final int LOGFILE_OPT        = 'l';// $NON-NLS-1$
        private static final int NONGUI_OPT         = 'n';// $NON-NLS-1$
        private static final int PROPFILE_OPT       = 'p';// $NON-NLS-1$
        private static final int PROPFILE2_OPT      = 'q';// $NON-NLS-1$
        private static final int REMOTE_OPT         = 'r';// $NON-NLS-1$
        private static final int SERVER_OPT         = 's';// $NON-NLS-1$
        private static final int TESTFILE_OPT       = 't';// $NON-NLS-1$
        private static final int PROXY_USERNAME     = 'u';// $NON-NLS-1$
        private static final int VERSION_OPT        = 'v';// $NON-NLS-1$
        private static final int REPORT_GENERATING_OPT  = 'g';// $NON-NLS-1$
        private static final int REPORT_AT_END_OPT      = 'e';// $NON-NLS-1$
        private static final int REPORT_OUTPUT_FOLDER_OPT      = 'o';// $NON-NLS-1$
        private static final int FORCE_DELETE_RESULT_FILE      = 'f';// $NON-NLS-1$
    
        private static final int SYSTEM_PROPERTY    = 'D';// $NON-NLS-1$
        private static final int JMETER_GLOBAL_PROP = 'G';// $NON-NLS-1$
        private static final int PROXY_SCHEME       = 'E';// $NON-NLS-1$
        private static final int PROXY_HOST         = 'H';// $NON-NLS-1$
        private static final int JMETER_PROPERTY    = 'J';// $NON-NLS-1$
        private static final int LOGLEVEL           = 'L';// $NON-NLS-1$
        private static final int NONPROXY_HOSTS     = 'N';// $NON-NLS-1$
        private static final int PROXY_PORT         = 'P';// $NON-NLS-1$
        private static final int REMOTE_OPT_PARAM   = 'R';// $NON-NLS-1$
        private static final int SYSTEM_PROPFILE    = 'S';// $NON-NLS-1$
        private static final int REMOTE_STOP        = 'X';// $NON-NLS-1$
    
        private static final String JMX_SUFFIX = ".JMX"; // $NON-NLS-1$
    
        private static final String PACKAGE_PREFIX = "org.apache."; //$NON_NLS-1$
    
        /**
         * Define the understood options. Each CLOptionDescriptor contains:
         * <ul>
         * <li>The "long" version of the option. Eg, "help" means that "--help"
         * will be recognised.</li>
         * <li>The option flags, governing the option's argument(s).</li>
         * <li>The "short" version of the option. Eg, 'h' means that "-h" will be
         * recognised.</li>
         * <li>A description of the option.</li>
         * </ul>
         */
        private static final CLOptionDescriptor D_OPTIONS_OPT =
                new CLOptionDescriptor("?", CLOptionDescriptor.ARGUMENT_DISALLOWED, OPTIONS_OPT,
                    "print command line options and exit");
        private static final CLOptionDescriptor D_HELP_OPT =
                new CLOptionDescriptor("help", CLOptionDescriptor.ARGUMENT_DISALLOWED, HELP_OPT,
                        "print usage information and exit");
        private static final CLOptionDescriptor D_VERSION_OPT =
                new CLOptionDescriptor("version", CLOptionDescriptor.ARGUMENT_DISALLOWED, VERSION_OPT,
                        "print the version information and exit");
        private static final CLOptionDescriptor D_PROPFILE_OPT =
                new CLOptionDescriptor("propfile", CLOptionDescriptor.ARGUMENT_REQUIRED, PROPFILE_OPT,
                        "the jmeter property file to use");
        private static final CLOptionDescriptor D_PROPFILE2_OPT =
                new CLOptionDescriptor("addprop", CLOptionDescriptor.ARGUMENT_REQUIRED
                        | CLOptionDescriptor.DUPLICATES_ALLOWED, PROPFILE2_OPT,
                        "additional JMeter property file(s)");
        private static final CLOptionDescriptor D_TESTFILE_OPT =
                new CLOptionDescriptor("testfile", CLOptionDescriptor.ARGUMENT_REQUIRED, TESTFILE_OPT,
                        "the jmeter test(.jmx) file to run. \"-t LAST\" will load last used file");
        private static final CLOptionDescriptor D_LOGFILE_OPT =
                new CLOptionDescriptor("logfile", CLOptionDescriptor.ARGUMENT_REQUIRED, LOGFILE_OPT,
                        "the file to log samples to");
        private static final CLOptionDescriptor D_JMLOGCONF_OPT =
                new CLOptionDescriptor("jmeterlogconf", CLOptionDescriptor.ARGUMENT_REQUIRED, JMLOGCONF_OPT,
                        "jmeter logging configuration file (log4j2.xml)");
        private static final CLOptionDescriptor D_JMLOGFILE_OPT =
                new CLOptionDescriptor("jmeterlogfile", CLOptionDescriptor.ARGUMENT_REQUIRED, JMLOGFILE_OPT,
                        "jmeter run log file (jmeter.log)");
        private static final CLOptionDescriptor D_NONGUI_OPT =
                new CLOptionDescriptor("nongui", CLOptionDescriptor.ARGUMENT_DISALLOWED, NONGUI_OPT,
                        "run JMeter in nongui mode");
        private static final CLOptionDescriptor D_SERVER_OPT =
                new CLOptionDescriptor("server", CLOptionDescriptor.ARGUMENT_DISALLOWED, SERVER_OPT,
                        "run the JMeter server");
        private static final CLOptionDescriptor D_PROXY_SCHEME =
                new CLOptionDescriptor("proxyScheme", CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_SCHEME,
                        "Set a proxy scheme to use for the proxy server");
        private static final CLOptionDescriptor D_PROXY_HOST =
                new CLOptionDescriptor("proxyHost", CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_HOST,
                        "Set a proxy server for JMeter to use");
        private static final CLOptionDescriptor D_PROXY_PORT =
                new CLOptionDescriptor("proxyPort", CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_PORT,
                        "Set proxy server port for JMeter to use");
        private static final CLOptionDescriptor D_NONPROXY_HOSTS =
                new CLOptionDescriptor("nonProxyHosts", CLOptionDescriptor.ARGUMENT_REQUIRED, NONPROXY_HOSTS,
                        "Set nonproxy host list (e.g. *.apache.org|localhost)");
        private static final CLOptionDescriptor D_PROXY_USERNAME =
                new CLOptionDescriptor("username", CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_USERNAME,
                        "Set username for proxy server that JMeter is to use");
        private static final CLOptionDescriptor D_PROXY_PASSWORD =
                new CLOptionDescriptor("password", CLOptionDescriptor.ARGUMENT_REQUIRED, PROXY_PASSWORD,
                        "Set password for proxy server that JMeter is to use");
        private static final CLOptionDescriptor D_JMETER_PROPERTY =
                new CLOptionDescriptor("jmeterproperty", CLOptionDescriptor.DUPLICATES_ALLOWED
                        | CLOptionDescriptor.ARGUMENTS_REQUIRED_2, JMETER_PROPERTY,
                        "Define additional JMeter properties");
        private static final CLOptionDescriptor D_JMETER_GLOBAL_PROP =
                new CLOptionDescriptor("globalproperty", CLOptionDescriptor.DUPLICATES_ALLOWED
                        | CLOptionDescriptor.ARGUMENTS_REQUIRED_2, JMETER_GLOBAL_PROP,
                        "Define Global properties (sent to servers)\n\t\te.g. -Gport=123 or -Gglobal.properties");
        private static final CLOptionDescriptor D_SYSTEM_PROPERTY =
                new CLOptionDescriptor("systemproperty", CLOptionDescriptor.DUPLICATES_ALLOWED
                        | CLOptionDescriptor.ARGUMENTS_REQUIRED_2, SYSTEM_PROPERTY,
                        "Define add
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

test猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值