You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by be...@apache.org on 2013/05/26 18:57:34 UTC
[09/28] git commit: Improved library for using JVM/JNI and updated
uses (in tests).
Improved library for using JVM/JNI and updated uses (in tests).
Review: https://reviews.apache.org/r/11270
Project: http://git-wip-us.apache.org/repos/asf/incubator-mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mesos/commit/233edea2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mesos/tree/233edea2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mesos/diff/233edea2
Branch: refs/heads/master
Commit: 233edea23871302be582ddba340cfc6c7c68ef30
Parents: 07c44ce
Author: Benjamin Hindman <be...@twitter.com>
Authored: Thu May 2 09:29:32 2013 -0700
Committer: Benjamin Hindman <be...@twitter.com>
Committed: Fri May 24 22:05:05 2013 -0700
----------------------------------------------------------------------
src/Makefile.am | 18 +-
src/jvm/java/io.hpp | 36 ++
src/jvm/java/lang.hpp | 31 ++
src/jvm/java/net.hpp | 26 +
src/jvm/jvm.cpp | 767 ++++++++++++++++++------------
src/jvm/jvm.hpp | 367 ++++++++++-----
src/jvm/org/apache/log4j.cpp | 16 +
src/jvm/org/apache/log4j.hpp | 69 +++
src/jvm/org/apache/zookeeper.hpp | 168 +++++++
src/tests/zookeeper_test.cpp | 72 +--
src/tests/zookeeper_test.hpp | 12 +-
src/tests/zookeeper_test_server.cpp | 201 ++------
src/tests/zookeeper_test_server.hpp | 55 +--
13 files changed, 1131 insertions(+), 707 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/Makefile.am
----------------------------------------------------------------------
diff --git a/src/Makefile.am b/src/Makefile.am
index 5ed3423..fe31707 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -552,14 +552,24 @@ CLEANFILES += $(MESOS_SOURCES_JAR)
# main libmesos.so.
noinst_LTLIBRARIES += libjava.la
-libjava_la_SOURCES = java/jni/convert.cpp java/jni/construct.cpp \
+libjava_la_SOURCES = \
+ java/jni/convert.cpp \
+ java/jni/convert.hpp \
+ java/jni/construct.cpp \
+ java/jni/construct.hpp \
java/jni/org_apache_mesos_Log.cpp \
java/jni/org_apache_mesos_MesosSchedulerDriver.cpp \
java/jni/org_apache_mesos_MesosExecutorDriver.cpp \
java/jni/org_apache_mesos_state_Variable.cpp \
- java/jni/org_apache_mesos_state_ZooKeeperState.cpp jvm/jvm.cpp
-
-libjava_la_SOURCES += java/jni/convert.hpp java/jni/construct.hpp jvm/jvm.hpp
+ java/jni/org_apache_mesos_state_ZooKeeperState.cpp \
+ jvm/jvm.cpp \
+ jvm/jvm.hpp \
+ jvm/java/io.hpp \
+ jvm/java/lang.hpp \
+ jvm/java/net.hpp \
+ jvm/org/apache/log4j.cpp \
+ jvm/org/apache/log4j.hpp \
+ jvm/org/apache/zookeeper.hpp
libjava_la_CPPFLAGS = $(MESOS_CPPFLAGS)
libjava_la_CPPFLAGS += $(JAVA_CPPFLAGS)
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/io.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/io.hpp b/src/jvm/java/io.hpp
new file mode 100644
index 0000000..fa0c60c
--- /dev/null
+++ b/src/jvm/java/io.hpp
@@ -0,0 +1,36 @@
+#ifndef __JAVA_IO_HPP__
+#define __JAVA_IO_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace io {
+
+class File : public Jvm::Object
+{
+public:
+ File(const std::string& pathname)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named("java/io/File")
+ .constructor()
+ .parameter(Jvm::get()->stringClass));
+
+ object = Jvm::get()->invoke(constructor, Jvm::get()->string(pathname));
+ }
+
+ void deleteOnExit()
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named("java/io/File")
+ .method("deleteOnExit")
+ .returns(Jvm::get()->voidClass));
+
+ Jvm::get()->invoke<void>(object, method);
+ }
+};
+
+} // namespace io {
+} // namespace java {
+
+#endif // __JAVA_IO_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/lang.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/lang.hpp b/src/jvm/java/lang.hpp
new file mode 100644
index 0000000..5eb365d
--- /dev/null
+++ b/src/jvm/java/lang.hpp
@@ -0,0 +1,31 @@
+#ifndef __JAVA_LANG_HPP__
+#define __JAVA_LANG_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace lang {
+
+class Throwable : public Jvm::Object
+{
+public:
+ Throwable(const std::string& message)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named("java/lang/Throwable")
+ .constructor()
+ .parameter(Jvm::get()->stringClass));
+
+ object = Jvm::get()->invoke(constructor, Jvm::get()->string(message));
+ }
+
+private:
+ friend void Jvm::check(JNIEnv* env); // For constructing default instances.
+
+ Throwable() {}
+};
+
+} // namespace lang {
+} // namespace java {
+
+#endif // __JAVA_LANG_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/java/net.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/java/net.hpp b/src/jvm/java/net.hpp
new file mode 100644
index 0000000..7816251
--- /dev/null
+++ b/src/jvm/java/net.hpp
@@ -0,0 +1,26 @@
+#ifndef __JAVA_NET_HPP__
+#define __JAVA_NET_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace java {
+namespace net {
+
+class InetSocketAddress : public Jvm::Object // TODO(benh): Extends SocketAddress.
+{
+public:
+ InetSocketAddress(int port)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named("java/net/InetSocketAddress")
+ .constructor()
+ .parameter(Jvm::get()->intClass));
+
+ object = Jvm::get()->invoke(constructor, port);
+ }
+};
+
+} // namespace net {
+} // namespace java {
+
+#endif // __JAVA_NET_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/jvm.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.cpp b/src/jvm/jvm.cpp
index a4fb791..d053f59 100644
--- a/src/jvm/jvm.cpp
+++ b/src/jvm/jvm.cpp
@@ -8,571 +8,714 @@
#include <sstream>
#include <vector>
-#include <stout/hashmap.hpp>
+#include <stout/exit.hpp>
#include <stout/foreach.hpp>
#include "jvm/jvm.hpp"
+#include "jvm/java/lang.hpp"
-namespace mesos {
-namespace internal {
-jmethodID Jvm::findMethod(const Jvm::JClass& clazz,
- const std::string& name,
- const Jvm::JClass& returnType,
- const std::vector<Jvm::JClass> argTypes,
- bool isStatic)
+// Static storage and initialization.
+Jvm* Jvm::instance = NULL;
+
+
+Try<Jvm*> Jvm::create(
+ const std::vector<std::string>& options,
+ JNI::Version version,
+ bool exceptions)
{
- std::ostringstream signature;
- signature << "(";
- std::vector<Jvm::JClass>::iterator args;
- foreach (Jvm::JClass type, argTypes) {
- signature << type.signature();
+ // TODO(benh): Make this thread-safe.
+ if (instance != NULL) {
+ return Error("Java Virtual Machine already created");
}
- signature << ")" << returnType.signature();
- LOG(INFO) << "looking up" << (isStatic ? " static " : " ") << "method "
- << name << signature.str();
-
- jmethodID id = NULL;
- if (isStatic) {
- id = env->GetStaticMethodID(findClass(clazz),
- name.c_str(),
- signature.str().c_str());
- } else {
- id = env->GetMethodID(findClass(clazz),
- name.c_str(),
- signature.str().c_str());
+ JavaVMInitArgs vmArgs;
+ vmArgs.version = version;
+ vmArgs.ignoreUnrecognized = false;
+
+ JavaVMOption* opts = new JavaVMOption[options.size()];
+ for (size_t i = 0; i < options.size(); i++) {
+ opts[i].optionString = const_cast<char*>(options[i].c_str());
}
+ vmArgs.nOptions = options.size();
+ vmArgs.options = opts;
- // TODO(John Sirois): consider CHECK -> return Option if re-purposing this
- // code outside of tests.
- CHECK(id != NULL);
- return id;
-}
+ JavaVM* jvm = NULL;
+ JNIEnv* env = NULL;
+ int result = JNI_CreateJavaVM(&jvm, JNIENV_CAST(&env), &vmArgs);
-Jvm::ConstructorFinder::ConstructorFinder(
- const Jvm::JClass& _type)
- : type(_type),
- parameters() {}
+ if (result == JNI_ERR) {
+ return Error("Failed to create JVM!");
+ }
+ delete[] opts;
-Jvm::ConstructorFinder&
-Jvm::ConstructorFinder::parameter(const Jvm::JClass& type)
-{
- parameters.push_back(type);
- return *this;
+ return instance = new Jvm(jvm, version, exceptions);
}
-Jvm::JConstructor Jvm::findConstructor(const ConstructorFinder& signature)
+bool Jvm::created()
{
- jmethodID id =
- findMethod(signature.type,
- "<init>",
- voidClass,
- signature.parameters,
- false);
- return Jvm::JConstructor(signature.type, id);
+ return instance != NULL;
}
-Jvm::JConstructor::JConstructor(const JConstructor& other) : clazz(other.clazz),
- id(other.id) {}
+Jvm* Jvm::get()
+{
+ if (instance == NULL) {
+ create();
+ }
+ return CHECK_NOTNULL(instance);
+}
-Jvm::JConstructor::JConstructor(const JClass& _clazz,
- const jmethodID _id) : clazz(_clazz),
- id(_id) {}
+Jvm::ConstructorFinder::ConstructorFinder(const Jvm::Class& _clazz)
+ : clazz(_clazz), parameters() {}
-jobject Jvm::invoke(const JConstructor& ctor, ...)
+Jvm::ConstructorFinder& Jvm::ConstructorFinder::parameter(
+ const Jvm::Class& clazz)
{
- va_list args;
- va_start(args, ctor);
- jobject result = env->NewObjectV(findClass(ctor.clazz), ctor.id, args);
- va_end(args);
- CHECK(result != NULL);
- return result;
+ parameters.push_back(clazz);
+ return *this;
}
+Jvm::Constructor::Constructor(const Constructor& that)
+ : clazz(that.clazz), id(that.id) {}
+
+
+Jvm::Constructor::Constructor(const Class& _clazz, const jmethodID _id)
+ : clazz(_clazz), id(_id) {}
+
+
Jvm::MethodFinder::MethodFinder(
- const Jvm::JClass& _clazz,
+ const Jvm::Class& _clazz,
const std::string& _name)
- : clazz(_clazz),
- name(_name),
- parameters() {}
+ : clazz(_clazz),
+ name(_name),
+ parameters() {}
-Jvm::MethodFinder& Jvm::MethodFinder::parameter(const JClass& type)
+Jvm::MethodFinder& Jvm::MethodFinder::parameter(const Class& type)
{
parameters.push_back(type);
return *this;
}
-Jvm::MethodSignature Jvm::MethodFinder::returns(const JClass& returnType) const
+Jvm::MethodSignature Jvm::MethodFinder::returns(const Class& returnType) const
{
return Jvm::MethodSignature(clazz, name, returnType, parameters);
}
-Jvm::JMethod Jvm::findMethod(const MethodSignature& signature)
-{
- jmethodID id = findMethod(signature.clazz,
- signature.name,
- signature.returnType,
- signature.parameters,
- false);
- return Jvm::JMethod(signature.clazz, id);
-}
-
-
-Jvm::JMethod Jvm::findStaticMethod(const MethodSignature& signature)
-{
- jmethodID id = findMethod(signature.clazz,
- signature.name,
- signature.returnType,
- signature.parameters,
- true);
- return Jvm::JMethod(signature.clazz, id);
-}
+Jvm::MethodSignature::MethodSignature(const MethodSignature& that)
+ : clazz(that.clazz),
+ name(that.name),
+ returnType(that.returnType),
+ parameters(that.parameters) {}
-Jvm::MethodSignature::MethodSignature(const MethodSignature& other) :
- clazz(other.clazz),
- name(other.name),
- returnType(other.returnType),
- parameters(other.parameters) {}
-
-
-Jvm::MethodSignature::MethodSignature(const JClass& _clazz,
- const std::string& _name,
- const JClass& _returnType,
- const std::vector<JClass>& _parameters) :
- clazz(_clazz),
+Jvm::MethodSignature::MethodSignature(
+ const Class& _clazz,
+ const std::string& _name,
+ const Class& _returnType,
+ const std::vector<Class>& _parameters)
+ : clazz(_clazz),
name(_name),
returnType(_returnType),
parameters(_parameters) {}
-Jvm::JMethod::JMethod(const JMethod& other)
- : clazz(other.clazz), id(other.id) {}
+Jvm::Method::Method(const Method& that)
+ : clazz(that.clazz), id(that.id) {}
-Jvm::JMethod::JMethod(const JClass& _clazz, const jmethodID _id)
+Jvm::Method::Method(const Class& _clazz, const jmethodID _id)
: clazz(_clazz), id(_id) {}
-template <>
-jobject Jvm::invokeV<jobject>(const jobject receiver,
- const jmethodID id,
- va_list args)
+const Jvm::Class Jvm::Class::named(const std::string& name)
{
- jobject result = env->CallObjectMethodV(receiver, id, args);
- CHECK(result != NULL);
- return result;
+ return Jvm::Class(name, false /* NOT a native type. */);
}
-template<>
-void Jvm::invokeV<void>(const jobject receiver,
- const jmethodID id,
- va_list args)
+Jvm::Class::Class(const Class& that)
+ : name(that.name), native(that.native) {}
+
+
+Jvm::Class::Class(const std::string& _name, bool _native)
+ : name(_name), native(_native) {}
+
+
+const Jvm::Class Jvm::Class::arrayOf() const
{
- env->CallVoidMethodV(receiver, id, args);
+ return Jvm::Class("[" + name, native);
}
-template <>
-bool Jvm::invokeV<bool>(const jobject receiver,
- const jmethodID id,
- va_list args)
+Jvm::ConstructorFinder Jvm::Class::constructor() const
{
- return env->CallBooleanMethodV(receiver, id, args);
+ return Jvm::ConstructorFinder(*this);
}
-template <>
-char Jvm::invokeV<char>(const jobject receiver,
- const jmethodID id,
- va_list args)
+Jvm::MethodFinder Jvm::Class::method(const std::string& name) const
{
- return env->CallCharMethodV(receiver, id, args);
+ return Jvm::MethodFinder(*this, name);
}
-template <>
-short Jvm::invokeV<short>(const jobject receiver,
- const jmethodID id,
- va_list args)
+std::string Jvm::Class::signature() const
{
- return env->CallShortMethodV(receiver, id, args);
+ return native ? name : "L" + name + ";";
}
-template <>
-int Jvm::invokeV<int>(const jobject receiver,
- const jmethodID id,
- va_list args)
+Jvm::Field::Field(const Field& that)
+ : clazz(that.clazz), id(that.id) {}
+
+
+Jvm::Field::Field(const Class& _clazz, const jfieldID _id)
+ : clazz(_clazz), id(_id) {}
+
+
+Jvm::Env::Env(bool daemon)
+ : env(NULL), detach(false)
{
- return env->CallIntMethodV(receiver, id, args);
-}
+ JavaVM* jvm = Jvm::get()->jvm;
+ // First check if we are already attached.
+ int result = jvm->GetEnv(JNIENV_CAST(&env), Jvm::get()->version);
-template <>
-long Jvm::invokeV<long>(const jobject receiver,
- const jmethodID id,
- va_list args)
+ // If we're not attached, attach now.
+ if (result == JNI_EDETACHED) {
+ if (daemon) {
+ jvm->AttachCurrentThreadAsDaemon(JNIENV_CAST(&env), NULL);
+ } else {
+ jvm->AttachCurrentThread(JNIENV_CAST(&env), NULL);
+ }
+ detach = true;
+ }
+}
+
+Jvm::Env::~Env()
{
- return env->CallLongMethodV(receiver, id, args);
+ if (detach) {
+ Jvm::get()->jvm->DetachCurrentThread();
+ }
}
-template <>
-float Jvm::invokeV<float>(const jobject receiver,
- const jmethodID id,
- va_list args)
+jstring Jvm::string(const std::string& s)
{
- return env->CallFloatMethodV(receiver, id, args);
+ Env env;
+ return env->NewStringUTF(s.c_str());
}
-template <>
-double Jvm::invokeV<double>(const jobject receiver,
- const jmethodID id,
- va_list args)
+Jvm::Constructor Jvm::findConstructor(const ConstructorFinder& finder)
{
- return env->CallDoubleMethodV(receiver, id, args);
+ jmethodID id = findMethod(
+ finder.clazz,
+ "<init>",
+ voidClass,
+ finder.parameters,
+ false);
+
+ return Jvm::Constructor(finder.clazz, id);
}
-template <>
-void Jvm::invoke<void>(const jobject receiver, const JMethod& method, ...)
+Jvm::Method Jvm::findMethod(const MethodSignature& signature)
{
- va_list args;
- va_start(args, method);
- invokeV<void>(receiver, method.id, args);
- va_end(args);
+ jmethodID id = findMethod(
+ signature.clazz,
+ signature.name,
+ signature.returnType,
+ signature.parameters,
+ false);
+
+ return Jvm::Method(signature.clazz, id);
}
-template <>
-jobject Jvm::invokeStaticV<jobject>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+Jvm::Method Jvm::findStaticMethod(const MethodSignature& signature)
{
- jobject result = env->CallStaticObjectMethodV(findClass(receiver), id, args);
- CHECK(result != NULL);
- return result;
+ jmethodID id = findMethod(
+ signature.clazz,
+ signature.name,
+ signature.returnType,
+ signature.parameters,
+ true);
+
+ return Jvm::Method(signature.clazz, id);
}
-template<>
-void Jvm::invokeStaticV<void>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+Jvm::Field Jvm::findStaticField(const Class& clazz, const std::string& name)
{
- env->CallStaticVoidMethodV(findClass(receiver), id, args);
+ Env env;
+
+ jfieldID id = env->GetStaticFieldID(
+ findClass(clazz),
+ name.c_str(),
+ clazz.signature().c_str());
+
+ check(env);
+
+ return Jvm::Field(clazz, id);
}
-template <>
-bool Jvm::invokeStaticV<bool>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+jobject Jvm::invoke(const Constructor& ctor, ...)
{
- return env->CallStaticBooleanMethodV(findClass(receiver), id, args);
+ Env env;
+ va_list args;
+ va_start(args, ctor);
+ jobject o = env->NewObjectV(findClass(ctor.clazz), ctor.id, args);
+ va_end(args);
+ check(env);
+ return o;
}
template <>
-char Jvm::invokeStaticV<char>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+jobject Jvm::getStaticField<jobject>(const Field& field)
{
- return env->CallStaticCharMethodV(findClass(receiver), id, args);
+ Env env;
+ jobject o = env->GetStaticObjectField(findClass(field.clazz), field.id);
+ check(env);
+ return o;
}
template <>
-short Jvm::invokeStaticV<short>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+bool Jvm::getStaticField<bool>(const Field& field)
{
- return env->CallStaticShortMethodV(findClass(receiver), id, args);
+ Env env;
+ bool b = env->GetStaticBooleanField(findClass(field.clazz), field.id);
+ check(env);
+ return b;
}
template <>
-int Jvm::invokeStaticV<int>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+char Jvm::getStaticField<char>(const Field& field)
{
- return env->CallStaticIntMethodV(findClass(receiver), id, args);
+ Env env;
+ char c = env->GetStaticCharField(findClass(field.clazz), field.id);
+ check(env);
+ return c;
}
template <>
-long Jvm::invokeStaticV<long>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+short Jvm::getStaticField<short>(const Field& field)
{
- return env->CallStaticLongMethodV(findClass(receiver), id, args);
+ Env env;
+ short s = env->GetStaticShortField(findClass(field.clazz), field.id);
+ check(env);
+ return s;
}
template <>
-float Jvm::invokeStaticV<float>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+int Jvm::getStaticField<int>(const Field& field)
{
- return env->CallStaticFloatMethodV(findClass(receiver), id, args);
+ Env env;
+ int i = env->GetStaticIntField(findClass(field.clazz), field.id);
+ check(env);
+ return i;
}
template <>
-double Jvm::invokeStaticV<double>(const JClass& receiver,
- const jmethodID id,
- va_list args)
+long Jvm::getStaticField<long>(const Field& field)
{
- return env->CallStaticDoubleMethodV(findClass(receiver), id, args);
+ Env env;
+ long l = env->GetStaticLongField(findClass(field.clazz), field.id);
+ check(env);
+ return l;
}
template <>
-void Jvm::invokeStatic<void>(const JMethod& method, ...)
+float Jvm::getStaticField<float>(const Field& field)
{
- va_list args;
- va_start(args, method);
- invokeStaticV<void>(method.clazz, method.id, args);
- va_end(args);
+ Env env;
+ float f = env->GetStaticFloatField(findClass(field.clazz), field.id);
+ check(env);
+ return f;
}
-const Jvm::JClass Jvm::JClass::forName(const std::string& nativeName)
+template <>
+double Jvm::getStaticField<double>(const Field& field)
{
- return Jvm::JClass(nativeName, false /* not a native type */);
+ Env env;
+ double d = env->GetStaticDoubleField(findClass(field.clazz), field.id);
+ check(env);
+ return d;
}
-Jvm::JClass::JClass(const JClass& other) : nativeName(other.nativeName),
- isNative(other.isNative) {}
-
-
-Jvm::JClass::JClass(const std::string& _nativeName,
- bool _isNative) : nativeName(_nativeName),
- isNative(_isNative) {}
+Jvm::Jvm(JavaVM* _jvm, JNI::Version _version, bool _exceptions)
+ : voidClass("V"),
+ booleanClass("Z"),
+ byteClass("B"),
+ charClass("C"),
+ shortClass("S"),
+ intClass("I"),
+ longClass("J"),
+ floatClass("F"),
+ doubleClass("D"),
+ stringClass(Class::named("java/lang/String")),
+ jvm(_jvm),
+ version(_version),
+ exceptions(_exceptions) {}
-const Jvm::JClass Jvm::JClass::arrayOf() const
+Jvm::~Jvm()
{
- return Jvm::JClass("[" + nativeName, isNative);
+ LOG(FATAL) << "Destroying the JVM is not supported";
}
-Jvm::ConstructorFinder Jvm::JClass::constructor() const
+jobject Jvm::newGlobalRef(const jobject object)
{
- return Jvm::ConstructorFinder(*this);
+ Env env;
+ return env->NewGlobalRef(object);
}
-Jvm::MethodFinder Jvm::JClass::method(const std::string& name) const
+void Jvm::deleteGlobalRef(const jobject object)
{
- return Jvm::MethodFinder(*this, name);
+ Env env;
+ if (object != NULL) {
+ env->DeleteGlobalRef(object);
+ }
}
-std::string Jvm::JClass::signature() const
+jclass Jvm::findClass(const Class& clazz)
{
- return isNative ? nativeName : "L" + nativeName + ";";
+ Env env;
+
+ // TODO(John Sirois): Consider CHECK_NOTNULL -> return Option if
+ // re-purposing this code outside of tests.
+ return CHECK_NOTNULL(env->FindClass(clazz.name.c_str()));
}
-Jvm::JField::JField(const JField& other) : clazz(other.clazz), id(other.id) {}
+jmethodID Jvm::findMethod(
+ const Jvm::Class& clazz,
+ const std::string& name,
+ const Jvm::Class& returnType,
+ const std::vector<Jvm::Class>& argTypes,
+ bool isStatic)
+{
+ Env env;
+ std::ostringstream signature;
+ signature << "(";
+ std::vector<Jvm::Class>::iterator args;
+ foreach (const Jvm::Class& type, argTypes) {
+ signature << type.signature();
+ }
+ signature << ")" << returnType.signature();
-Jvm::JField::JField(const JClass& _clazz, const jfieldID _id)
- : clazz(_clazz), id(_id) {}
+ LOG(INFO) << "Looking up" << (isStatic ? " static " : " ")
+ << "method " << name << signature.str();
+ jmethodID id = isStatic
+ ? env->GetStaticMethodID(
+ findClass(clazz),
+ name.c_str(),
+ signature.str().c_str())
+ : env->GetMethodID(
+ findClass(clazz),
+ name.c_str(),
+ signature.str().c_str());
-Jvm::JField Jvm::findStaticField(const JClass& clazz, const std::string& name)
-{
- jfieldID id =
- env->GetStaticFieldID(findClass(clazz),
- name.c_str(),
- clazz.signature().c_str());
- return Jvm::JField(clazz, id);
+ // TODO(John Sirois): Consider CHECK_NOTNULL -> return Option if
+ // re-purposing this code outside of tests.
+ return CHECK_NOTNULL(id);
}
-template <>
-jobject Jvm::getStaticField<jobject>(const JField& field)
+template<>
+void Jvm::invokeV<void>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- jobject result = env->GetStaticObjectField(findClass(field.clazz), field.id);
- CHECK(result != NULL);
- return result;
+ Env env;
+ env->CallVoidMethodV(receiver, id, args);
+ check(env);
}
template <>
-bool Jvm::getStaticField<bool>(const JField& field)
+jobject Jvm::invokeV<jobject>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticBooleanField(findClass(field.clazz), field.id);
+ Env env;
+ jobject o = env->CallObjectMethodV(receiver, id, args);
+ check(env);
+ return o;
}
template <>
-char Jvm::getStaticField<char>(const JField& field)
+bool Jvm::invokeV<bool>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticCharField(findClass(field.clazz), field.id);
+ Env env;
+ bool b = env->CallBooleanMethodV(receiver, id, args);
+ check(env);
+ return b;
}
template <>
-short Jvm::getStaticField<short>(const JField& field)
+char Jvm::invokeV<char>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticShortField(findClass(field.clazz), field.id);
+ Env env;
+ char c = env->CallCharMethodV(receiver, id, args);
+ check(env);
+ return c;
}
template <>
-int Jvm::getStaticField<int>(const JField& field)
+short Jvm::invokeV<short>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticIntField(findClass(field.clazz), field.id);
+ Env env;
+ short s = env->CallShortMethodV(receiver, id, args);
+ check(env);
+ return s;
}
template <>
-long Jvm::getStaticField<long>(const JField& field)
+int Jvm::invokeV<int>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticLongField(findClass(field.clazz), field.id);
+ Env env;
+ int i = env->CallIntMethodV(receiver, id, args);
+ check(env);
+ return i;
}
template <>
-float Jvm::getStaticField<float>(const JField& field)
+long Jvm::invokeV<long>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticFloatField(findClass(field.clazz), field.id);
+ Env env;
+ long l = env->CallLongMethodV(receiver, id, args);
+ check(env);
+ return l;
}
template <>
-double Jvm::getStaticField<double>(const JField& field)
+float Jvm::invokeV<float>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->GetStaticDoubleField(findClass(field.clazz), field.id);
+ Env env;
+ float f = env->CallFloatMethodV(receiver, id, args);
+ check(env);
+ return f;
}
-Jvm::Jvm(const std::vector<std::string>& options, JNIVersion jniVersion)
- : voidClass("V"),
- booleanClass("Z"),
- byteClass("B"),
- charClass("C"),
- shortClass("S"),
- intClass("I"),
- longClass("J"),
- floatClass("F"),
- doubleClass("D"),
- stringClass(JClass::forName("java/lang/String")),
- jvm(NULL),
- env(NULL)
+template <>
+double Jvm::invokeV<double>(
+ const jobject receiver,
+ const jmethodID id,
+ va_list args)
{
- JavaVMInitArgs vmArgs;
- vmArgs.version = jniVersion;
- vmArgs.ignoreUnrecognized = false;
-
- JavaVMOption* opts = new JavaVMOption[options.size()];
- for (size_t i = 0; i < options.size(); i++) {
- opts[i].optionString = const_cast<char*>(options[i].c_str());
- }
- vmArgs.nOptions = options.size();
- vmArgs.options = opts;
-
- int result = JNI_CreateJavaVM(&jvm, JNIENV_CAST(&env), &vmArgs);
- CHECK(result != JNI_ERR) << "Failed to create JVM!";
-
- delete[] opts;
+ Env env;
+ double d = env->CallDoubleMethodV(receiver, id, args);
+ check(env);
+ return d;
}
-Jvm::~Jvm()
+template<>
+void Jvm::invokeStaticV<void>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- CHECK(0 == jvm->DestroyJavaVM()) << "Failed to destroy JVM";
+ Env env;
+ env->CallStaticVoidMethodV(findClass(receiver), id, args);
+ check(env);
}
-void Jvm::attachDaemon()
+template <>
+jobject Jvm::invokeStaticV<jobject>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- jvm->AttachCurrentThreadAsDaemon(JNIENV_CAST(&env), NULL);
+ Env env;
+ jobject o = env->CallStaticObjectMethodV(findClass(receiver), id, args);
+ check(env);
+ return o;
}
-void Jvm::attach()
+template <>
+bool Jvm::invokeStaticV<bool>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- jvm->AttachCurrentThread(JNIENV_CAST(&env), NULL);
+ Env env;
+ bool b = env->CallStaticBooleanMethodV(findClass(receiver), id, args);
+ check(env);
+ return b;
}
-void Jvm::detach()
+template <>
+char Jvm::invokeStaticV<char>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- jvm->DetachCurrentThread();
+ Env env;
+ char c = env->CallStaticCharMethodV(findClass(receiver), id, args);
+ check(env);
+ return c;
}
-jclass Jvm::findClass(const JClass& clazz)
+template <>
+short Jvm::invokeStaticV<short>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- jclass cls = env->FindClass(clazz.nativeName.c_str());
- // TODO(John Sirois): consider CHECK -> return Option if re-purposing this
- // code outside of tests.
- CHECK(cls != NULL);
- return cls;
+ Env env;
+ short s = env->CallStaticShortMethodV(findClass(receiver), id, args);
+ check(env);
+ return s;
}
-jobject Jvm::string(const std::string& str)
+template <>
+int Jvm::invokeStaticV<int>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->NewStringUTF(str.c_str());
+ Env env;
+ int i = env->CallStaticIntMethodV(findClass(receiver), id, args);
+ check(env);
+ return i;
}
-jobject Jvm::newGlobalRef(const jobject object)
+template <>
+long Jvm::invokeStaticV<long>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- return env->NewGlobalRef(object);
+ Env env;
+ long l = env->CallStaticLongMethodV(findClass(receiver), id, args);
+ check(env);
+ return l;
}
-void Jvm::deleteGlobalRef(const jobject object)
+template <>
+float Jvm::invokeStaticV<float>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
{
- env->DeleteGlobalRef(object);
+ Env env;
+ float f = env->CallStaticFloatMethodV(findClass(receiver), id, args);
+ check(env);
+ return f;
}
-void Jvm::deleteGlobalRefSafe(const jobject object)
-{
- if (object != NULL) {
- deleteGlobalRef(object);
+template <>
+double Jvm::invokeStaticV<double>(
+ const Class& receiver,
+ const jmethodID id,
+ va_list args)
+{
+ Env env;
+ double d = env->CallStaticDoubleMethodV(findClass(receiver), id, args);
+ check(env);
+ return d;
+}
+
+
+void Jvm::check(JNIEnv* env)
+{
+ if (env->ExceptionCheck() == JNI_TRUE) {
+ if (!exceptions) {
+ env->ExceptionDescribe();
+ EXIT(1) << "Caught a JVM exception, not propagating";
+ } else {
+ java::lang::Throwable throwable;
+ Object* object = &throwable;
+ object->object = env->ExceptionOccurred();
+ env->ExceptionClear();
+ throw throwable;
+ }
}
}
-Jvm::Attach::Attach(Jvm* jvm, bool daemon) : _jvm(jvm)
+
+// N.B. Both Jvm::invoke<void> and Jvm::invokeStatic<void> template
+// instantiations need to be defined AFTER template instantions that
+// they use (i.e., Jvm::invokeV<void>, Jvm::invokeStaticV<void>).
+
+template <>
+void Jvm::invoke<void>(const jobject receiver, const Method& method, ...)
{
- if (daemon) {
- _jvm->attachDaemon();
- } else {
- _jvm->attach();
- }
+ va_list args;
+ va_start(args, method);
+ invokeV<void>(receiver, method.id, args);
+ va_end(args);
}
-Jvm::Attach::~Attach()
+template <>
+void Jvm::invokeStatic<void>(const Method& method, ...)
{
- // TODO(John Sirois): this detaches too early under nested use, attach by a
- // given thread should incr, this should decr and only detach on 0
- _jvm->detach();
+ va_list args;
+ va_start(args, method);
+ invokeStaticV<void>(method.clazz, method.id, args);
+ va_end(args);
}
-
-} // namespace internal
-} // namespace mesos
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/jvm.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/jvm.hpp b/src/jvm/jvm.hpp
index 6a31bd8..a3ea86a 100644
--- a/src/jvm/jvm.hpp
+++ b/src/jvm/jvm.hpp
@@ -3,10 +3,13 @@
#include <jni.h>
-#include <glog/logging.h>
-
+#include <string>
#include <vector>
+#include <stout/error.hpp>
+#include <stout/try.hpp>
+
+
// Some compilers give us warnings about 'dereferencing type-punned
// pointer will break strict-aliasing rules' when we cast our JNIEnv**
// to void**. We use this function to do the magic for us.
@@ -16,118 +19,149 @@ inline void** JNIENV_CAST(JNIEnv** env)
}
-namespace mesos {
-namespace internal {
+struct JNI
+{
+ enum Version
+ {
+ v_1_1 = JNI_VERSION_1_1,
+ v_1_2 = JNI_VERSION_1_2,
+ v_1_4 = JNI_VERSION_1_4,
+ v_1_6 = JNI_VERSION_1_6
+ };
+};
-// Facilitates embedding a jvm and calling into it.
-//
-// TODO(John Sirois): Fix variadic methods. Possibly a way to do this with
-// typelists, type concatenation and unwinding builder inheritance.
-//
-// TODO(John Sirois): Support finding static methods.
+// Facilitates embedding a JVM and calling into it.
class Jvm
{
public:
// Forward declarations.
class ConstructorFinder;
class MethodFinder;
- class JConstructor;
+ class Constructor;
class MethodSignature;
- class JMethod;
-
- // An opaque class descriptor that can be used to find constructors, methods
- // and fields.
- class JClass
+ class Method;
+
+ // Starts a new embedded JVM with the given -D options. Each option
+ // supplied should be of the standard form: '-Dproperty=value'.
+ // Returns the singleton Jvm instance or an error if the JVM had
+ // already been created. Note that you can only create one JVM
+ // instance per process since destructing a JVM has issues, see:
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4712793. In
+ // addition, most JVM's use signals and couldn't possibly play
+ // nicely with one another.
+ // TODO(benh): Add a 'create' which just takes an already
+ // constructed JavaVM. This will be useful for when a JVM is calling
+ // into native code versus native code embedding a JVM.
+ // TODO(John Sirois): Consider elevating classpath as a top-level
+ // JVM configuration parameter since it will likely always need to
+ // be specified. Ditto for and non '-X' options.
+ static Try<Jvm*> create(
+ const std::vector<std::string>& options = std::vector<std::string>(),
+ JNI::Version version = JNI::v_1_6,
+ bool exceptions = false);
+
+ // Returns true if the JVM has already been created.
+ static bool created();
+
+ // Returns the singleton JVM instance, creating it with no options
+ // and a default version if necessary.
+ static Jvm* get();
+
+ // An opaque class descriptor that can be used to find constructors,
+ // methods and fields.
+ class Class
{
public:
- // A factory for new java reference type class descriptors given the native
- // name. To obtain class descriptors for native types, use the fields in
- // Jvm.
- static const JClass forName(const std::string& nativeName);
+ // A factory for new Java reference type class descriptors given
+ // the fully-qualified class name (e.g., 'java/io/File'). To
+ // obtain class descriptors for native types (int, short, etc),
+ // use the fields in Jvm.
+ static const Class named(const std::string& name);
- JClass(const JClass& other);
+ Class(const Class& that);
// Returns the class of an array of the current class.
- const JClass arrayOf() const;
+ const Class arrayOf() const;
- // Creates a builder that can be used to locate a constructor of this
- // class with Jvm::findConstructor.
+ // Creates a builder that can be used to locate a constructor of
+ // this class with Jvm::findConstructor.
ConstructorFinder constructor() const;
- // Creates a builder that can be used to locate an instance method of this
- // class with Jvm::findMethod.
+ // Creates a builder that can be used to locate an instance method
+ // of this class with Jvm::findMethod.
MethodFinder method(const std::string& name) const;
private:
friend class Jvm;
- JClass(const std::string& nativeName,
- bool isNative = true);
+ Class(const std::string& name, bool native = true);
std::string signature() const;
- std::string nativeName;
- bool isNative;
+ std::string name;
+ bool native;
};
- // A builder that is used to specify a constructor by specifying its parameter
- // list with zero or more calls to ConstructorFinder::parameter.
+ // A builder that is used to specify a constructor by specifying its
+ // parameter list with zero or more calls to
+ // ConstructorFinder::parameter.
class ConstructorFinder
{
public:
// Adds a parameter to the constructor parameter list.
- ConstructorFinder& parameter(const JClass& type);
+ ConstructorFinder& parameter(const Class& clazz);
private:
- friend class JClass;
+ friend class Class;
friend class Jvm;
- ConstructorFinder(const JClass& type);
+ ConstructorFinder(const Class& clazz);
- const JClass type;
- std::vector<JClass> parameters;
+ const Class clazz;
+ std::vector<Class> parameters;
};
- // An opaque constructor descriptor that can be used to create new instances
- // of a class using Jvm::invokeConstructor.
- class JConstructor
+ // An opaque constructor descriptor that can be used to create new
+ // instances of a class using Jvm::invokeConstructor.
+ class Constructor
{
public:
- JConstructor(const JConstructor& other);
+ Constructor(const Constructor& that);
private:
friend class Jvm;
- JConstructor(const JClass& clazz, const jmethodID id);
+ Constructor(const Class& clazz, const jmethodID id);
- const JClass clazz;
+ const Class clazz;
const jmethodID id;
};
- // A builder that is used to specify an instance method by specifying its
- // parameter list with zero or more calls to MethodFinder::parameter and a
- // final call to MethodFinder::returns to get an opaque specification of the
- // method for use with Jvm::findMethod.
+ // A builder that is used to specify an instance method by
+ // specifying its parameter list with zero or more calls to
+ // MethodFinder::parameter and a final call to MethodFinder::returns
+ // to get an opaque specification of the method for use with
+ // Jvm::findMethod.
class MethodFinder
{
public:
// Adds a parameter to the method parameter list.
- MethodFinder& parameter(const JClass& type);
+ MethodFinder& parameter(const Class& type);
// Terminates description of a method by specifying its return type.
- MethodSignature returns(const JClass& type) const;
+ MethodSignature returns(const Class& type) const;
private:
- friend class JClass;
+ friend class Class;
- MethodFinder(const JClass& clazz, const std::string& name);
+ MethodFinder(const Class& clazz, const std::string& name);
- const JClass clazz;
+ const Class clazz;
const std::string name;
- std::vector<JClass> parameters;
+ std::vector<Class> parameters;
};
@@ -135,153 +169,237 @@ public:
class MethodSignature
{
public:
- MethodSignature(const MethodSignature& other);
+ MethodSignature(const MethodSignature& that);
private:
friend class Jvm;
friend class MethodFinder;
- MethodSignature(const JClass& clazz,
+ MethodSignature(const Class& clazz,
const std::string& name,
- const JClass& returnType,
- const std::vector<JClass>& parameters);
+ const Class& returnType,
+ const std::vector<Class>& parameters);
- const JClass clazz;
+ const Class clazz;
const std::string name;
- const JClass returnType;
- std::vector<JClass> parameters;
+ const Class returnType;
+ std::vector<Class> parameters;
};
// An opaque method descriptor that can be used to invoke instance methods
// using Jvm::invokeMethod.
- class JMethod
+ class Method
{
public:
- JMethod(const JMethod& other);
+ Method(const Method& that);
private:
friend class Jvm;
friend class MethodSignature;
- JMethod(const JClass& clazz, const jmethodID id);
+ Method(const Class& clazz, const jmethodID id);
- const JClass clazz;
+ const Class clazz;
const jmethodID id;
};
// An opaque field descriptor that can be used to access fields using
// methods like Jvm::getStaticField.
- class JField
+ class Field
{
public:
- JField(const JField& other);
+ Field(const Field& that);
private:
friend class Jvm;
- JField(const JClass& clazz, const jfieldID id);
+ Field(const Class& clazz, const jfieldID id);
- const JClass clazz;
+ const Class clazz;
const jfieldID id;
};
- // RAII container for c++/jvm thread binding management.
- class Attach
+ // Base class for all JVM objects. This object "stores" the
+ // underlying global reference and performs the appropriate
+ // operations across copies and assignments.
+ class Object
{
public:
- Attach(Jvm* jvm, bool daemon = true);
- ~Attach();
+ Object() : object(NULL) {}
+
+ Object(jobject _object)
+ : object(Jvm::get()->newGlobalRef(_object)) {}
+
+ Object(const Object& that)
+ {
+ object = Jvm::get()->newGlobalRef(that.object);
+ }
+
+ ~Object()
+ {
+ if (object != NULL) {
+ Jvm::get()->deleteGlobalRef(object);
+ }
+ }
+
+ Object& operator = (const Object& that)
+ {
+ if (object != NULL) {
+ Jvm::get()->deleteGlobalRef(object);
+ }
+ object = Jvm::get()->newGlobalRef(that.object);
+ return *this;
+ }
+
+ operator jobject () const
+ {
+ return object;
+ }
+
+ protected:
+ friend class Jvm; // For manipulating object.
+
+ jobject object;
+ };
+
+ // Helper for providing access to static variables in a class. You
+ // can use this to delay the variable lookup until it's actually
+ // accessed in order to keep the JVM from getting constructed too
+ // early. See Level in jvm/org/apache/log4j.hpp for an example.
+ // TODO(benh): Make this work for instance variables too (i.e.,
+ // StaticVariable -> Variable).
+ // TODO(benh): Provide template specialization for primitive
+ // types (e.g., StaticVariable<int>, StaticVariable<short>,
+ // StaticVariable<std::string>).
+ template <typename T, const char* name>
+ class StaticVariable
+ {
+ public:
+ StaticVariable(const Class& _clazz)
+ : clazz(_clazz)
+ {
+ // Check that T extends Object.
+ { T* t = NULL; Object* o = t; (void) o; }
+ }
+
+ operator T () const
+ {
+ // Note that we actually look up the field lazily (upon first
+ // invocation operator) so that we don't possibly create the JVM
+ // too early.
+ static Field field = Jvm::get()->findStaticField(clazz, name);
+ T t;
+ t.object = Jvm::get()->getStaticField<jobject>(field);
+ return t;
+ }
private:
- Jvm* _jvm;
+ const Class clazz;
};
- friend class Attach;
-
- enum JNIVersion
+ // Each thread that wants to interact with the JVM needs a JNI
+ // environment which must be obtained by "attaching" to the JVM. We
+ // use the following RAII class to provide the environment and also
+ // make sure a thread is attached and properly detached. Note that
+ // nested constructions are no-ops and use the same environment (and
+ // without detaching too early).
+ // TODO(benh): Support putting a 'Jvm::Env' into a thread-local
+ // variable so we can "attach" to the JVM once.
+ class Env
{
- v_1_1 = JNI_VERSION_1_1,
- v_1_2 = JNI_VERSION_1_2,
- v_1_4 = JNI_VERSION_1_4,
- v_1_6 = JNI_VERSION_1_6
+ public:
+ Env(bool daemon = true);
+ ~Env();
+
+ JNIEnv* operator -> () const { return env; }
+
+ operator JNIEnv* () const { return env; }
+
+ private:
+ JNIEnv* env;
+ bool detach; // A nested use of Env should not detach the thread.
};
- // Starts a new embedded jvm with the given -D options. Each option supplied
- // should be of the standard form: '-Dproperty=value'.
- //
- // TODO(John Sirois): Consider elevating classpath as a top level jvm
- // configuration parameter since it will likely always need to be specified.
- // Ditto for and non -X java option.
- Jvm(const std::vector<std::string>& options,
- JNIVersion jniVersion = Jvm::v_1_6);
- ~Jvm();
+ friend class Env;
- const JClass voidClass;
- const JClass booleanClass;
- const JClass byteClass;
- const JClass charClass;
- const JClass shortClass;
- const JClass intClass;
- const JClass longClass;
- const JClass floatClass;
- const JClass doubleClass;
- const JClass stringClass;
+ const Class voidClass;
+ const Class booleanClass;
+ const Class byteClass;
+ const Class charClass;
+ const Class shortClass;
+ const Class intClass;
+ const Class longClass;
+ const Class floatClass;
+ const Class doubleClass;
+ const Class stringClass;
- jobject string(const std::string& str);
+ jstring string(const std::string& s);
- JConstructor findConstructor(const ConstructorFinder& constructor);
- JMethod findMethod(const MethodSignature& signature);
- JMethod findStaticMethod(const MethodSignature& signature);
- JField findStaticField(const JClass& clazz, const std::string& name);
+ Constructor findConstructor(const ConstructorFinder& finder);
+ Method findMethod(const MethodSignature& signature);
+ Method findStaticMethod(const MethodSignature& signature);
+ Field findStaticField(const Class& clazz, const std::string& name);
- jobject invoke(const JConstructor& ctor, ...);
+ // TODO(John Sirois): Add "type checking" to variadic method
+ // calls. Possibly a way to do this with typelists, type
+ // concatenation and unwinding builder inheritance.
+
+ jobject invoke(const Constructor& ctor, ...);
template <typename T>
- T invoke(const jobject receiver, const JMethod& method, ...);
+ T invoke(const jobject receiver, const Method& method, ...);
template <typename T>
- T invokeStatic(const JMethod& method, ...);
+ T invokeStatic(const Method& method, ...);
template <typename T>
- T getStaticField(const JField& field);
+ T getStaticField(const Field& field);
+
+ // Checks the exception state of an environment.
+ void check(JNIEnv* env);
+private:
+ friend class Object; // For creating global references.
+
+ Jvm(JavaVM* jvm, JNI::Version version, bool exceptions);
+ ~Jvm();
+
+private:
jobject newGlobalRef(const jobject object);
void deleteGlobalRef(const jobject object);
- void deleteGlobalRefSafe(const jobject object);
-private:
- jclass findClass(const JClass& clazz);
+ jclass findClass(const Class& clazz);
- jmethodID findMethod(const Jvm::JClass& clazz,
+ jmethodID findMethod(const Jvm::Class& clazz,
const std::string& name,
- const Jvm::JClass& returnType,
- const std::vector<Jvm::JClass> argTypes,
+ const Jvm::Class& returnType,
+ const std::vector<Jvm::Class>& argTypes,
bool isStatic);
template <typename T>
T invokeV(const jobject receiver, const jmethodID id, va_list args);
template <typename T>
- T invokeStaticV(const JClass& receiver, const jmethodID id, va_list args);
+ T invokeStaticV(const Class& receiver, const jmethodID id, va_list args);
- void attachDaemon();
- void attach();
- void detach();
+ // Singleton instance.
+ static Jvm* instance;
JavaVM* jvm;
- JNIEnv* env;
+ const JNI::Version version;
+ const bool exceptions;
};
template <>
-void Jvm::invoke<void>(const jobject receiver, const JMethod& method, ...);
+void Jvm::invoke<void>(const jobject receiver, const Method& method, ...);
template <typename T>
-T Jvm::invoke(const jobject receiver, const JMethod& method, ...)
+T Jvm::invoke(const jobject receiver, const Method& method, ...)
{
va_list args;
va_start(args, method);
@@ -292,11 +410,11 @@ T Jvm::invoke(const jobject receiver, const JMethod& method, ...)
template <>
-void Jvm::invokeStatic<void>(const JMethod& method, ...);
+void Jvm::invokeStatic<void>(const Method& method, ...);
template <typename T>
-T Jvm::invokeStatic(const JMethod& method, ...)
+T Jvm::invokeStatic(const Method& method, ...)
{
va_list args;
va_start(args, method);
@@ -305,7 +423,4 @@ T Jvm::invokeStatic(const JMethod& method, ...)
return result;
}
-} // namespace internal
-} // namespace mesos
-
#endif // __JVM_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/log4j.cpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.cpp b/src/jvm/org/apache/log4j.cpp
new file mode 100644
index 0000000..b73df8c
--- /dev/null
+++ b/src/jvm/org/apache/log4j.cpp
@@ -0,0 +1,16 @@
+#include <jvm/org/apache/log4j.hpp>
+
+namespace org {
+namespace apache {
+namespace log4j {
+
+// Static storage and initialization.
+const char LEVEL_OFF[] = "OFF";
+
+Jvm::StaticVariable<Level, LEVEL_OFF> Level::OFF =
+ Jvm::StaticVariable<Level, LEVEL_OFF>(
+ Jvm::Class::named("org/apache/log4j/Level"));
+
+} // namespace log4j {
+} // namespace apache {
+} // namespace org {
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/log4j.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/log4j.hpp b/src/jvm/org/apache/log4j.hpp
new file mode 100644
index 0000000..6b5ba4b
--- /dev/null
+++ b/src/jvm/org/apache/log4j.hpp
@@ -0,0 +1,69 @@
+#ifndef __ORG_APACHE_LOG4J_HPP__
+#define __ORG_APACHE_LOG4J_HPP__
+
+#include <jvm/jvm.hpp>
+
+namespace org {
+namespace apache {
+namespace log4j {
+
+// Forward declaration.
+extern const char LEVEL_OFF[];
+
+
+class Level : public Jvm::Object // TODO(benh): Extends Priority.
+{
+public:
+ friend class Jvm::StaticVariable<Level, LEVEL_OFF>;
+
+ static Jvm::StaticVariable<Level, LEVEL_OFF> OFF;
+
+ Level() {} // No default constuctors.
+};
+
+
+class Category : public Jvm::Object
+{
+public:
+ void setLevel(const Level& level)
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named("org/apache/log4j/Category")
+ .method("setLevel")
+ .parameter(Jvm::Class::named("org/apache/log4j/Level"))
+ .returns(Jvm::get()->voidClass));
+
+ Jvm::get()->invoke<void>(object, method, (jobject) level);
+ }
+
+protected:
+ Category() {} // No default constructors.
+};
+
+
+class Logger : public Category
+{
+public:
+ static Logger getRootLogger()
+ {
+ static Jvm::Method method = Jvm::get()->findStaticMethod(
+ Jvm::Class::named("org/apache/log4j/Logger")
+ .method("getRootLogger")
+ .returns(Jvm::Class::named("org/apache/log4j/Logger")));
+
+ Logger logger;
+ logger.object = Jvm::get()->invokeStatic<jobject>(method);
+
+ return logger;
+ }
+
+protected:
+ Logger() {} // No default constructors.
+};
+
+
+} // namespace log4j {
+} // namespace apache {
+} // namespace org {
+
+#endif // __ORG_APACHE_LOG4J_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/jvm/org/apache/zookeeper.hpp
----------------------------------------------------------------------
diff --git a/src/jvm/org/apache/zookeeper.hpp b/src/jvm/org/apache/zookeeper.hpp
new file mode 100644
index 0000000..dac1456
--- /dev/null
+++ b/src/jvm/org/apache/zookeeper.hpp
@@ -0,0 +1,168 @@
+#ifndef __ORG_APACHE_ZOOKEEPER_HPP__
+#define __ORG_APACHE_ZOOKEEPER_HPP__
+
+#include <jvm/jvm.hpp>
+
+#include <jvm/java/io.hpp>
+#include <jvm/java/net.hpp>
+
+// Package 'org.apache.zookeeper.persistence'.
+
+namespace org {
+namespace apache {
+namespace zookeeper {
+namespace persistence {
+
+class FileTxnSnapLog : public Jvm::Object
+{
+public:
+ FileTxnSnapLog(const java::io::File& dataDir,
+ const java::io::File& snapDir)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/persistence/FileTxnSnapLog")
+ .constructor()
+ .parameter(Jvm::Class::named("java/io/File"))
+ .parameter(Jvm::Class::named("java/io/File")));
+
+ object = Jvm::get()->invoke(
+ constructor, (jobject) dataDir, (jobject) snapDir);
+ }
+};
+
+} // namespace persistence {
+} // namespace zookeeper {
+} // namespace apache {
+} // namespace org {
+
+
+// Package 'org.apache.zookeeper.server'.
+
+namespace org {
+namespace apache {
+namespace zookeeper {
+namespace server {
+
+class ZooKeeperServer : public Jvm::Object
+{
+public:
+ class DataTreeBuilder : public Jvm::Object {};
+
+ class BasicDataTreeBuilder : public DataTreeBuilder
+ {
+ public:
+ BasicDataTreeBuilder()
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/ZooKeeperServer$BasicDataTreeBuilder")
+ .constructor());
+
+ object = Jvm::get()->invoke(constructor);
+ }
+ };
+
+ ZooKeeperServer(const persistence::FileTxnSnapLog& txnLogFactory,
+ const DataTreeBuilder& treeBuilder)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+ .constructor()
+ .parameter(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/persistence/FileTxnSnapLog"))
+ .parameter(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/ZooKeeperServer$DataTreeBuilder")));
+
+ object = Jvm::get()->invoke(
+ constructor, (jobject) txnLogFactory, (jobject) treeBuilder);
+ }
+
+ int getClientPort()
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+ .method("getClientPort")
+ .returns(Jvm::get()->intClass));
+
+ return Jvm::get()->invoke<int>(object, method);
+ }
+
+ void closeSession(int64_t sessionId)
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named("org/apache/zookeeper/server/ZooKeeperServer")
+ .method("closeSession")
+ .parameter(Jvm::get()->longClass)
+ .returns(Jvm::get()->voidClass));
+
+ Jvm::get()->invoke<void>(object, method, sessionId);
+ }
+};
+
+
+class NIOServerCnxn : public Jvm::Object
+{
+public:
+ class Factory : public Jvm::Object // TODO(benh): Extends Thread.
+ {
+ public:
+ Factory(const java::net::InetSocketAddress& addr)
+ {
+ static Jvm::Constructor constructor = Jvm::get()->findConstructor(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+ .constructor()
+ .parameter(Jvm::Class::named("java/net/InetSocketAddress")));
+
+ object = Jvm::get()->invoke(constructor, (jobject) addr);
+ }
+
+ void startup(const ZooKeeperServer& zks)
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+ .method("startup")
+ .parameter(Jvm::Class::named(
+ "org/apache/zookeeper/server/ZooKeeperServer"))
+ .returns(Jvm::get()->voidClass));
+
+ Jvm::get()->invoke<void>(object, method, (jobject) zks);
+ }
+
+ bool isAlive()
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+ .method("isAlive")
+ .returns(Jvm::get()->booleanClass));
+
+ return Jvm::get()->invoke<bool>(object, method);
+ }
+
+ void shutdown()
+ {
+ static Jvm::Method method = Jvm::get()->findMethod(
+ Jvm::Class::named(
+ "org/apache/zookeeper/server/NIOServerCnxn$Factory")
+ .method("shutdown")
+ .returns(Jvm::get()->voidClass));
+
+ Jvm::get()->invoke<void>(object, method);
+ }
+ };
+
+private:
+ NIOServerCnxn() {} // No default constructors.
+};
+
+} // namespace server {
+} // namespace zookeeper {
+} // namespace apache {
+} // namespace org {
+
+#endif // __ORG_APACHE_ZOOKEEPER_HPP__
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.cpp b/src/tests/zookeeper_test.cpp
index fb61f2d..90c6aba 100644
--- a/src/tests/zookeeper_test.cpp
+++ b/src/tests/zookeeper_test.cpp
@@ -24,14 +24,17 @@
#include <tr1/functional>
+#include <jvm/jvm.hpp>
+
+#include <jvm/org/apache/log4j.hpp>
+#include <jvm/org/apache/log4j.hpp>
+
#include <stout/lambda.hpp>
#include "common/lock.hpp"
#include "logging/logging.hpp"
-#include "jvm/jvm.hpp"
-
#include "tests/utils.hpp"
#include "tests/zookeeper_test.hpp"
#include "tests/zookeeper_test_server.hpp"
@@ -40,45 +43,12 @@ namespace mesos {
namespace internal {
namespace tests {
-const Milliseconds ZooKeeperTest::NO_TIMEOUT(5000);
-
-// Note that we NEVER delete the Jvm instance because you can only
-// create one JVM since destructing a JVM has issues (see:
-// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4712793).
-Jvm* ZooKeeperTest::jvm = NULL;
-
-
-static void silenceServerLogs(Jvm* jvm)
-{
- Jvm::Attach attach(jvm);
-
- Jvm::JClass loggerClass = Jvm::JClass::forName("org/apache/log4j/Logger");
- jobject rootLogger =jvm->invokeStatic<jobject>(
- jvm->findStaticMethod(loggerClass
- .method("getRootLogger")
- .returns(loggerClass)));
-
- Jvm::JClass levelClass = Jvm::JClass::forName("org/apache/log4j/Level");
- jvm->invoke<void>(
- rootLogger,
- jvm->findMethod(loggerClass
- .method("setLevel")
- .parameter(levelClass)
- .returns(jvm->voidClass)),
- jvm->getStaticField<jobject>(jvm->findStaticField(levelClass, "OFF")));
-}
-
-
-static void silenceClientLogs()
-{
- // TODO(jsirois): Put this in the C++ API.
- zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
-}
+const Duration ZooKeeperTest::NO_TIMEOUT = Milliseconds(5000);
void ZooKeeperTest::SetUpTestCase()
{
- if (jvm == NULL) {
+ if (!Jvm::created()) {
std::string zkHome = flags.build_dir +
"/third_party/zookeeper-" ZOOKEEPER_VERSION;
@@ -88,13 +58,19 @@ void ZooKeeperTest::SetUpTestCase()
LOG(INFO) << "Using classpath setup: " << classpath << std::endl;
- std::vector<std::string> opts;
- opts.push_back(classpath);
- jvm = new Jvm(opts);
+ std::vector<std::string> options;
+ options.push_back(classpath);
+ Try<Jvm*> jvm = Jvm::create(options);
+ CHECK_SOME(jvm);
if (!flags.verbose) {
- silenceServerLogs(jvm);
- silenceClientLogs();
+ // Silence server logs.
+ org::apache::log4j::Logger::getRootLogger()
+ .setLevel(org::apache::log4j::Level::OFF);
+
+ // Silence client logs.
+ // TODO(jsirois): Create C++ ZooKeeper::setLevel.
+ zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR);
}
}
}
@@ -102,18 +78,8 @@ void ZooKeeperTest::SetUpTestCase()
void ZooKeeperTest::SetUp()
{
- MesosTest::SetUp();
- server = new ZooKeeperTestServer(jvm);
server->startNetwork();
-};
-
-
-void ZooKeeperTest::TearDown()
-{
- delete server;
- server = NULL;
- MesosTest::TearDown();
-};
+}
ZooKeeperTest::TestWatcher::TestWatcher()
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test.hpp b/src/tests/zookeeper_test.hpp
index 61a3d25..7bd396b 100644
--- a/src/tests/zookeeper_test.hpp
+++ b/src/tests/zookeeper_test.hpp
@@ -29,8 +29,6 @@
#include <stout/duration.hpp>
-#include "jvm/jvm.hpp"
-
#include "tests/utils.hpp"
#include "tests/zookeeper_test_server.hpp"
@@ -82,7 +80,6 @@ public:
class TestWatcher : public Watcher
{
public:
-
// Encapsulates all the state of a ZooKeeper watcher event.
struct Event {
Event(int _type, int _state, const std::string& _path)
@@ -119,21 +116,18 @@ public:
pthread_cond_t cond;
};
- ZooKeeperTest() : server(NULL) {}
+ ZooKeeperTest() : server(new ZooKeeperTestServer()) {}
+ virtual ~ZooKeeperTest() { delete server; }
static void SetUpTestCase();
protected:
virtual void SetUp();
- virtual void TearDown();
// A very long session timeout that simulates no timeout for test cases.
- static const Milliseconds NO_TIMEOUT;
+ static const Duration NO_TIMEOUT;
ZooKeeperTestServer* server;
-
-private:
- static Jvm* jvm;
};
} // namespace tests {
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test_server.cpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.cpp b/src/tests/zookeeper_test_server.cpp
index 5c82a1e..8051b4d 100644
--- a/src/tests/zookeeper_test_server.cpp
+++ b/src/tests/zookeeper_test_server.cpp
@@ -16,130 +16,48 @@
* limitations under the License.
*/
-#include <jni.h>
-#include <stdarg.h>
+#include <jvm/jvm.hpp>
-#include <glog/logging.h>
+#include <jvm/java/io.hpp>
+#include <jvm/java/net.hpp>
-#include <sstream>
-#include <vector>
+#include <jvm/org/apache/zookeeper.hpp>
-#include <stout/uuid.hpp>
+#include <stout/os.hpp>
-#include "jvm/jvm.hpp"
+#include "logging/logging.hpp"
#include "tests/zookeeper_test_server.hpp"
+using org::apache::zookeeper::persistence::FileTxnSnapLog;
+
+using org::apache::zookeeper::server::NIOServerCnxn;
+using org::apache::zookeeper::server::ZooKeeperServer;
+
namespace mesos {
namespace internal {
namespace tests {
-ZooKeeperTestServer::ZooKeeperTestServer(Jvm* _jvm)
- : jvm(_jvm),
+ZooKeeperTestServer::ZooKeeperTestServer()
+ : zooKeeperServer(NULL),
+ connectionFactory(NULL),
port(0),
started(false)
{
- Jvm::Attach attach(jvm);
-
- Jvm::JClass fileClass = Jvm::JClass::forName("java/io/File");
- fileConstructor = new Jvm::JConstructor(
- jvm->findConstructor(
- fileClass
- .constructor()
- .parameter(jvm->stringClass)));
-
- Jvm::JClass inetSocketAddressClass =
- Jvm::JClass::forName("java/net/InetSocketAddress");
- inetSocketAddressConstructor = new Jvm::JConstructor(
- jvm->findConstructor(
- inetSocketAddressClass
- .constructor()
- .parameter(jvm->intClass)));
-
- Jvm::JClass cnxnFactoryClass =
- Jvm::JClass::forName("org/apache/zookeeper/server/NIOServerCnxn$Factory");
- cnxnFactoryConstructor = new Jvm::JConstructor(
- jvm->findConstructor(
- cnxnFactoryClass
- .constructor()
- .parameter(inetSocketAddressClass)));
-
- Jvm::JClass zkServerClass =
- Jvm::JClass::forName("org/apache/zookeeper/server/ZooKeeperServer");
- startup = new Jvm::JMethod(
- jvm->findMethod(
- cnxnFactoryClass
- .method("startup")
- .parameter(zkServerClass)
- .returns(jvm->voidClass)));
-
- isAlive = new Jvm::JMethod(
- jvm->findMethod(
- cnxnFactoryClass
- .method("isAlive")
- .returns(jvm->booleanClass)));
-
- shutdown = new Jvm::JMethod(
- jvm->findMethod(
- cnxnFactoryClass
- .method("shutdown")
- .returns(jvm->voidClass)));
-
- dataDir = createTempDir();
- snapDir = createTempDir();
- Jvm::JClass snapLogClass =
- Jvm::JClass::forName(
- "org/apache/zookeeper/server/"
- "persistence/FileTxnSnapLog");
-
- snapLog = jvm->newGlobalRef(
- jvm->invoke(
- jvm->findConstructor(snapLogClass
- .constructor()
- .parameter(fileClass)
- .parameter(fileClass)),
- dataDir->file,
- snapDir->file));
-
- dataTreeBuilder = jvm->newGlobalRef(
- jvm->invoke(
- jvm->findConstructor(
- Jvm::JClass::forName(
- "org/apache/zookeeper/server/"
- "ZooKeeperServer$BasicDataTreeBuilder").constructor())));
-
- Jvm::JClass dataTreeBuilderClass(
- Jvm::JClass::forName("org/apache/zookeeper/server/"
- "ZooKeeperServer$DataTreeBuilder"));
-
- zooKeeperServer = jvm->newGlobalRef(
- jvm->invoke(
- jvm->findConstructor(zkServerClass
- .constructor()
- .parameter(snapLogClass)
- .parameter(dataTreeBuilderClass)),
- snapLog,
- dataTreeBuilder));
-
- getClientPort = new Jvm::JMethod(
- jvm->findMethod(zkServerClass
- .method("getClientPort")
- .returns(jvm->intClass)));
-
- closeSession = new Jvm::JMethod(
- jvm->findMethod(zkServerClass
- .method("closeSession")
- .parameter(jvm->longClass)
- .returns(jvm->voidClass)));
-}
-
-
-const ZooKeeperTestServer::TemporaryDirectory* ZooKeeperTestServer::createTempDir()
-{
- std::string tmpdir = "/tmp/zks-" + UUID::random().toString();
- jobject file =
- jvm->newGlobalRef(jvm->invoke(*fileConstructor, jvm->string(tmpdir)));
- return new TemporaryDirectory(jvm, tmpdir, file);
+ // Create temporary directories for the FileTxnSnapLog.
+ Try<std::string> directory = os::mkdtemp();
+ CHECK_SOME(directory);
+ java::io::File dataDir(directory.get());
+ dataDir.deleteOnExit();
+
+ directory = os::mkdtemp();
+ CHECK_SOME(directory);
+ java::io::File snapDir(directory.get());
+ snapDir.deleteOnExit();
+
+ zooKeeperServer = new ZooKeeperServer(
+ FileTxnSnapLog(dataDir, snapDir),
+ ZooKeeperServer::BasicDataTreeBuilder());
}
@@ -147,51 +65,30 @@ ZooKeeperTestServer::~ZooKeeperTestServer()
{
shutdownNetwork();
- Jvm::Attach attach(jvm);
-
- jvm->deleteGlobalRefSafe(inetSocketAddress);
- jvm->deleteGlobalRefSafe(connectionFactory);
- jvm->deleteGlobalRefSafe(snapLog);
- jvm->deleteGlobalRefSafe(dataTreeBuilder);
- jvm->deleteGlobalRefSafe(zooKeeperServer);
-
- delete fileConstructor;
- delete getClientPort;
- delete closeSession;
-
- delete inetSocketAddressConstructor;
- delete cnxnFactoryConstructor;
-
- delete startup;
- delete isAlive;
- delete shutdown;
-
- delete dataDir;
- delete snapDir;
+ delete zooKeeperServer;
+ delete connectionFactory;
}
void ZooKeeperTestServer::expireSession(int64_t sessionId)
{
- Jvm::Attach attach(jvm);
-
- jvm->invoke<void>(zooKeeperServer, *closeSession, sessionId);
+ zooKeeperServer->closeSession(sessionId);
}
std::string ZooKeeperTestServer::connectString() const
{
- checkStarted();
+ CHECK(port > 0) << "Illegal state, must call startNetwork first!";
return "127.0.0.1:" + stringify(port);
}
void ZooKeeperTestServer::shutdownNetwork()
{
- Jvm::Attach attach(jvm);
-
- if (started && jvm->invoke<bool>(connectionFactory, *isAlive)) {
- jvm->invoke<void>(connectionFactory, *shutdown);
+ if (started && connectionFactory->isAlive()) {
+ connectionFactory->shutdown();
+ delete connectionFactory;
+ connectionFactory = NULL;
LOG(INFO) << "Shutdown ZooKeeperTestServer on port " << port << std::endl;
}
}
@@ -199,28 +96,24 @@ void ZooKeeperTestServer::shutdownNetwork()
int ZooKeeperTestServer::startNetwork()
{
- Jvm::Attach attach(jvm);
+ connectionFactory = new NIOServerCnxn::Factory(
+ java::net::InetSocketAddress(port));
- inetSocketAddress =
- jvm->newGlobalRef(jvm->invoke(*inetSocketAddressConstructor, port));
- connectionFactory =
- jvm->newGlobalRef(
- jvm->invoke(*cnxnFactoryConstructor, inetSocketAddress));
+ connectionFactory->startup(*zooKeeperServer);
+
+ if (port == 0) {
+ // We save the ephemeral port so if/when we restart the network
+ // the clients will reconnect to the same server. Note that this
+ // might not actually be kosher because it's possible that another
+ // process could bind to our ephemeral port after we unbind.
+ port = zooKeeperServer->getClientPort();
+ }
- jvm->invoke<void>(connectionFactory, *startup, zooKeeperServer);
- port = jvm->invoke<int>(zooKeeperServer, *getClientPort);
LOG(INFO) << "Started ZooKeeperTestServer on port " << port;
started = true;
return port;
}
-
-void ZooKeeperTestServer::checkStarted() const
-{
- CHECK(port > 0) << "Illegal state, must call startNetwork first!";
-}
-
} // namespace tests {
} // namespace internal {
} // namespace mesos {
-
http://git-wip-us.apache.org/repos/asf/incubator-mesos/blob/233edea2/src/tests/zookeeper_test_server.hpp
----------------------------------------------------------------------
diff --git a/src/tests/zookeeper_test_server.hpp b/src/tests/zookeeper_test_server.hpp
index bfa841c..97a8524 100644
--- a/src/tests/zookeeper_test_server.hpp
+++ b/src/tests/zookeeper_test_server.hpp
@@ -19,13 +19,13 @@
#ifndef __ZOOKEEPER_TEST_SERVER_HPP__
#define __ZOOKEEPER_TEST_SERVER_HPP__
-#include <jni.h>
+#include <string>
#include <glog/logging.h>
-#include <stout/os.hpp>
+#include <jvm/org/apache/zookeeper.hpp>
-#include "jvm/jvm.hpp"
+#include <stout/os.hpp>
#include "zookeeper/zookeeper.hpp"
@@ -40,7 +40,7 @@ namespace tests {
class ZooKeeperTestServer
{
public:
- ZooKeeperTestServer(Jvm* jvm);
+ ZooKeeperTestServer();
~ZooKeeperTestServer();
// Gets a connection string that can be used to attach a ZooKeeper client to
@@ -67,54 +67,11 @@ public:
void expireSession(int64_t sessionId);
private:
- // TODO(John Sirois): factor out TemporaryDirectory + createTempDir() to utils
- struct TemporaryDirectory
- {
- Jvm* jvm;
- const std::string path;
- const jobject file;
-
- TemporaryDirectory(Jvm* _jvm,
- const std::string& _path,
- const jobject _file) : jvm(_jvm),
- path(_path),
- file(_file) {}
-
- ~TemporaryDirectory()
- {
- jvm->deleteGlobalRef(file);
- Try<Nothing> rmdir = os::rmdir(path);
- if (rmdir.isError()) {
- LOG(WARNING) << "Failed to delete temp dir '"
- << path << "': " << rmdir.error();
- }
- }
- };
-
- Jvm* jvm;
-
- Jvm::JConstructor* fileConstructor;
- jobject snapLog;
- jobject dataTreeBuilder;
- jobject zooKeeperServer;
- Jvm::JMethod* getClientPort;
- Jvm::JMethod* closeSession;
-
- Jvm::JConstructor* inetSocketAddressConstructor;
- jobject inetSocketAddress;
- Jvm::JConstructor* cnxnFactoryConstructor;
- jobject connectionFactory;
- Jvm::JMethod* startup;
- Jvm::JMethod* isAlive;
- Jvm::JMethod* shutdown;
+ org::apache::zookeeper::server::ZooKeeperServer* zooKeeperServer;
+ org::apache::zookeeper::server::NIOServerCnxn::Factory* connectionFactory;
int port;
bool started;
- const TemporaryDirectory* dataDir;
- const TemporaryDirectory* snapDir;
-
- const TemporaryDirectory* createTempDir();
- void checkStarted() const;
};
} // namespace tests {