mirror of
https://github.com/apple/foundationdb.git
synced 2025-05-17 03:12:21 +08:00
Allow classPath to be modified at runtime
This commit is contained in:
parent
e19901186f
commit
371a41dbba
@ -22,6 +22,13 @@ package com.apple.foundationdb.testing;
|
|||||||
|
|
||||||
import com.apple.foundationdb.Database;
|
import com.apple.foundationdb.Database;
|
||||||
import com.apple.foundationdb.FDB;
|
import com.apple.foundationdb.FDB;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
@ -31,6 +38,7 @@ import java.util.concurrent.SynchronousQueue;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class AbstractWorkload {
|
public abstract class AbstractWorkload {
|
||||||
|
private static final Class[] parameters = new Class[]{URL.class};
|
||||||
protected WorkloadContext context;
|
protected WorkloadContext context;
|
||||||
private ThreadPoolExecutor executorService;
|
private ThreadPoolExecutor executorService;
|
||||||
|
|
||||||
@ -99,4 +107,29 @@ public abstract class AbstractWorkload {
|
|||||||
private native void setProcessID(long processID);
|
private native void setProcessID(long processID);
|
||||||
private native void sendVoid(long handle);
|
private native void sendVoid(long handle);
|
||||||
private native void sendBool(long handle, boolean value);
|
private native void sendBool(long handle, boolean value);
|
||||||
|
|
||||||
|
// Helper functions to add to the class path at Runtime - will be called
|
||||||
|
// from C++
|
||||||
|
private static void addFile(String s) throws IOException {
|
||||||
|
File f = new File(s);
|
||||||
|
addFile(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addFile(File f) throws IOException {
|
||||||
|
addURL(f.toURI().toURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addURL(URL u) throws IOException {
|
||||||
|
URLClassLoader sysLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||||
|
Class sysClass = URLClassLoader.class;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Method method = sysClass.getDeclaredMethod("addURL", parameters);
|
||||||
|
method.setAccessible(true);
|
||||||
|
method.invoke(sysLoader, new Object[]{u});
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
throw new IOException("Error, could not add URL to system classloader");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,7 @@ struct JVMContext {
|
|||||||
// this is a bit ugly - but JNINativeMethod requires
|
// this is a bit ugly - but JNINativeMethod requires
|
||||||
// char* not const char *
|
// char* not const char *
|
||||||
std::vector<char*> charArrays;
|
std::vector<char*> charArrays;
|
||||||
|
std::set<std::string> classPath;
|
||||||
|
|
||||||
void setWorkloadMethods(const std::initializer_list<std::tuple<StringRef, StringRef, void*>>& methods) {
|
void setWorkloadMethods(const std::initializer_list<std::tuple<StringRef, StringRef, void*>>& methods) {
|
||||||
charArrays.reserve(charArrays.size() + 2*methods.size());
|
charArrays.reserve(charArrays.size() + 2*methods.size());
|
||||||
@ -175,6 +176,30 @@ struct JVMContext {
|
|||||||
flushTraceFileVoid();
|
flushTraceFileVoid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool addToClassPath(const std::string& path) {
|
||||||
|
TraceEvent("TryAddToClassPath")
|
||||||
|
.detail("Path", "path");
|
||||||
|
flushTraceFileVoid();
|
||||||
|
if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (classPath.count(path) > 0) {
|
||||||
|
// already added
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
auto addFileMethod = env->GetStaticMethodID(workloadClass, "addFile", "(Ljava/lang/String;)V");
|
||||||
|
if (!checkException()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto p = env->NewStringUTF(path.c_str());
|
||||||
|
env->CallStaticVoidMethod(workloadClass, addFileMethod, p);
|
||||||
|
if (!checkException()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
classPath.insert(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool checkException() {
|
bool checkException() {
|
||||||
auto flag = env->ExceptionCheck();
|
auto flag = env->ExceptionCheck();
|
||||||
if (flag) {
|
if (flag) {
|
||||||
@ -261,6 +286,7 @@ struct JavaWorkload : TestWorkload {
|
|||||||
// This means, that we have to share the VM across workloads.
|
// This means, that we have to share the VM across workloads.
|
||||||
static std::weak_ptr<JVMContext> globalVM;
|
static std::weak_ptr<JVMContext> globalVM;
|
||||||
std::shared_ptr<JVMContext> vm;
|
std::shared_ptr<JVMContext> vm;
|
||||||
|
std::vector<std::string> classPath;
|
||||||
|
|
||||||
std::string className;
|
std::string className;
|
||||||
|
|
||||||
@ -275,6 +301,7 @@ struct JavaWorkload : TestWorkload {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto jvmOptions = getOption(options, LiteralStringRef("jvmOptions"), std::vector<std::string>{});
|
auto jvmOptions = getOption(options, LiteralStringRef("jvmOptions"), std::vector<std::string>{});
|
||||||
|
classPath = getOption(options, LiteralStringRef("classPath"), std::vector<std::string>{});
|
||||||
vm = globalVM.lock();
|
vm = globalVM.lock();
|
||||||
if (!vm) {
|
if (!vm) {
|
||||||
std::vector<char*> args;
|
std::vector<char*> args;
|
||||||
@ -292,6 +319,8 @@ struct JavaWorkload : TestWorkload {
|
|||||||
success = vm->success;
|
success = vm->success;
|
||||||
}
|
}
|
||||||
if (success) {
|
if (success) {
|
||||||
|
TraceEvent("JVMRunning");
|
||||||
|
flushTraceFileVoid();
|
||||||
try {
|
try {
|
||||||
createContext();
|
createContext();
|
||||||
} catch (Error& e) {
|
} catch (Error& e) {
|
||||||
@ -332,6 +361,19 @@ struct JavaWorkload : TestWorkload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void createContext() {
|
void createContext() {
|
||||||
|
TraceEvent("AddClassPaths")
|
||||||
|
.detail("Num", classPath.size());
|
||||||
|
flushTraceFileVoid();
|
||||||
|
for (const auto& p : classPath) {
|
||||||
|
if (!vm->addToClassPath(p)) {
|
||||||
|
TraceEvent("AddToClassPathFailed")
|
||||||
|
.detail("Path", p);
|
||||||
|
success = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TraceEvent("AddToClassPath")
|
||||||
|
.detail("Path", p);
|
||||||
|
}
|
||||||
std::transform(className.begin(), className.end(), className.begin(), [](char c) {
|
std::transform(className.begin(), className.end(), className.begin(), [](char c) {
|
||||||
if (c == '.') return '/';
|
if (c == '.') return '/';
|
||||||
return c;
|
return c;
|
||||||
@ -379,6 +421,7 @@ struct JavaWorkload : TestWorkload {
|
|||||||
vm->env->CallVoidMethod(hashMap, put, key, value);
|
vm->env->CallVoidMethod(hashMap, put, key, value);
|
||||||
vm->env->DeleteLocalRef(key);
|
vm->env->DeleteLocalRef(key);
|
||||||
vm->env->DeleteLocalRef(value);
|
vm->env->DeleteLocalRef(value);
|
||||||
|
kv.value = LiteralStringRef("");
|
||||||
}
|
}
|
||||||
auto workloadContextClass = findClass("com/apple/foundationdb/testing/WorkloadContext");
|
auto workloadContextClass = findClass("com/apple/foundationdb/testing/WorkloadContext");
|
||||||
auto workloadContextConstructor = getMethodID(workloadContextClass, "<init>", "(Ljava/util/Map;IIJJ)V");
|
auto workloadContextConstructor = getMethodID(workloadContextClass, "<init>", "(Ljava/util/Map;IIJJ)V");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user