概述
启动JMeter,主要通过NewDriver来实现,直接用于本地 GUI 和非 GUI 调用。
启动类主要做启动时设置项目目录,加载lib目录下的所有依赖包,并反射调用JMeter类的start()方法。
代码位置
代码解读
主要变量
代码语言:txt复制 private static final String CLASSPATH_SEPARATOR = File.pathSeparator;
// 获取操作系统
private static final String OS_NAME = System.getProperty("os.name");
// 获取语言
private static final String OS_NAME_LC = OS_NAME.toLowerCase(java.util.Locale.ENGLISH);
// 获取java classPath
private static final String JAVA_CLASS_PATH = "java.class.path";
// 获取jmeter的logfile
private static final String JMETER_LOGFILE_SYSTEM_PROPERTY = "jmeter.logfile";
private static final String HEADLESS_MODE_PROPERTY = "java.awt.headless";
// 动态加载器,主要加载Java依赖包
private static final DynamicClassLoader loader;
private static final String JMETER_INSTALLATION_DIRECTORY; // JMeter的安装路径
private static final List<Exception> EXCEPTIONS_IN_INIT = new ArrayList<>();
静态代码块
主要是加载lib目录下的所有依赖包
代码语言:txt复制static {
final List<URL> jars = new LinkedList<>();
final String initiaClasspath = System.getProperty(JAVA_CLASS_PATH);
// Find JMeter home dir from the initial classpath
String tmpDir;
// 将获取的classPath进行拆分,分组
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 {
// JMeter启动类默认找当前文件路径的父目录
tmpDir = jar.getCanonicalFile().getParentFile().getParent();
} catch (IOException e) {
tmpDir = null;
}
} else {// e.g. started from IDE with full classpath
/*
* JMeter启动类默认找当前文件路径的父目录,由于生成的ApacheJMeter.jar启动包放置到JMeter的bin目录,所以获取的父目录正好是项目当前的目录,
* 但是我们要调用的时候要手动设置jmeter.home这个属性,否则启动会报错
*/
tmpDir = System.getProperty("jmeter.home","");// Allow override $NON-NLS-1$ $NON-NLS-2$
if (tmpDir.length() == 0) {
File userDir = new File(System.getProperty("user.dir"));// $NON-NLS-1$
tmpDir = userDir.getAbsoluteFile().getParent();
}
}
// JMeter项目路径
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
// 获取lib目录下的所有依赖包
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());
// 通过加载器将所有jar包加载到类加载器中
loader = AccessController.doPrivileged(
(PrivilegedAction<DynamicClassLoader>) () ->
new DynamicClassLoader(jars.toArray(new URL[jars.size()]))
);
}
主要方法
加载外部依赖包
根据文件URL动态加载到loader
代码语言:txt复制 public static void addURL(URL url) {
loader.addURL(url);
}
根据包的文件目录,获取当前文件路径及子路径的依赖包,转换为URL,并加载到loader中
代码语言:txt复制 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
}
}
获取JMeter项目路径
代码语言:txt复制 public static String getJMeterDir() {
return JMETER_INSTALLATION_DIRECTORY;
}
启动JMeter程序
通过Java反射的方法创建JMeter类,执行其start()方法
代码语言:txt复制 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");
}
// 通过Java反射的方法创建JMeter类,并执行start()方法
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
}
}
}