summaryrefslogtreecommitdiff
path: root/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/bindings/javahl/native/jniwrapper/jni_env.hpp')
-rw-r--r--subversion/bindings/javahl/native/jniwrapper/jni_env.hpp682
1 files changed, 682 insertions, 0 deletions
diff --git a/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp b/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
new file mode 100644
index 0000000..9d73653
--- /dev/null
+++ b/subversion/bindings/javahl/native/jniwrapper/jni_env.hpp
@@ -0,0 +1,682 @@
+/**
+ * @copyright
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ * @endcopyright
+ */
+
+#ifndef SVN_JAVAHL_JNIWRAPPER_ENV_HPP
+#define SVN_JAVAHL_JNIWRAPPER_ENV_HPP
+
+#include <jni.h>
+#include <cstdarg>
+#include <stdexcept>
+
+#ifdef SVN_JAVAHL_DEBUG
+# ifndef SVN_JAVAHL_JNIWRAPPER_LOG
+# include <iostream>
+# define SVN_JAVAHL_JNIWRAPPER_LOG(expr) \
+ (std::cerr << expr << std::endl)
+# endif // SVN_JAVAHL_JNIWRAPPER_LOG
+#else
+# define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
+#endif // SVN_JAVAHL_DEBUG
+
+namespace Java {
+
+/**
+ * A C++ exception object for signalling that a Java exception has
+ * been thrown.
+ *
+ * Thrown to unwind the stack while avoiding code clutter when a Java
+ * exception is detected in the JNI environment.
+ *
+ * @since New in 1.9.
+ */
+class SignalExceptionThrown {};
+
+/**
+ * Auto-initializing proxy for the JNI method ID.
+ *
+ * Behaves like a @c jmethodID but automatically initializes to @c NULL.
+ *
+ * @since New in 1.9.
+ */
+class MethodID
+{
+public:
+ MethodID()
+ : m_mid(NULL)
+ {}
+
+ MethodID(jmethodID mid)
+ : m_mid(mid)
+ {}
+
+ MethodID(const MethodID& that)
+ : m_mid(that.m_mid)
+ {}
+
+ MethodID& operator=(jmethodID mid)
+ {
+ m_mid = mid;
+ return *this;
+ }
+
+ MethodID& operator=(const MethodID& that)
+ {
+ m_mid = that.m_mid;
+ return *this;
+ }
+
+ operator jmethodID() const
+ {
+ return m_mid;
+ }
+
+ operator bool() const
+ {
+ return (NULL != m_mid);
+ }
+
+private:
+ jmethodID m_mid;
+};
+
+
+/**
+ * Auto-initializing proxy for the JNI field ID.
+ *
+ * Behaves like a @c jfieldID but automatically initializes to @c NULL.
+ *
+ * @since New in 1.9.
+ */
+class FieldID
+{
+public:
+ FieldID()
+ : m_fid(NULL)
+ {}
+
+ FieldID(jfieldID mid)
+ : m_fid(mid)
+ {}
+
+ FieldID(const FieldID& that)
+ : m_fid(that.m_fid)
+ {}
+
+ FieldID& operator=(jfieldID fid)
+ {
+ m_fid = fid;
+ return *this;
+ }
+
+ FieldID& operator=(const FieldID& that)
+ {
+ m_fid = that.m_fid;
+ return *this;
+ }
+
+ operator jfieldID() const
+ {
+ return m_fid;
+ }
+
+ operator bool() const
+ {
+ return (NULL != m_fid);
+ }
+
+private:
+ jfieldID m_fid;
+};
+
+/**
+ * Encapsulation of a JNI environment reference.
+ *
+ * This class wraps all (relevant) JNI functions and checks for thrown
+ * exceptions, so that call sites don't have to be cluttered with KNI
+ * exception checks.
+ *
+ * @since New in 1.9.
+ */
+class Env
+{
+public:
+ /**
+ * Constructs an environment object, retrieving the JNI environment
+ * reference from the global JVM reference.
+ */
+ explicit Env()
+ : m_env(env_from_jvm())
+ {}
+
+ /**
+ * Given a JNI renvironment reference, constructs an environment object.
+ */
+ explicit Env(::JNIEnv* env)
+ : m_env(env)
+ {}
+
+ /**
+ * Returns the wrapped JNI environment reference.
+ *
+ * This method is present for compatibility with the old-style
+ * native implmentation that needs the raw pointer, and will be
+ * removed presently. Do not use it in new-style code.
+ */
+ ::JNIEnv* get() const
+ {
+ SVN_JAVAHL_JNIWRAPPER_LOG("Warning: Direct access to JNIEnv at "
+ << __FILE__ << ":" << __LINE__);
+ return m_env;
+ }
+
+ /** Wrapped JNI function. */
+ jobject NewGlobalRef(jobject obj) const
+ {
+ jobject ret = m_env->NewGlobalRef(obj);
+ check_java_exception();
+ if (!ret)
+ throw_java_out_of_memory(error_create_global_reference());
+ return ret;
+ }
+
+ /** Wrapped JNI function. */
+ void DeleteGlobalRef(jobject obj) const throw()
+ {
+ m_env->DeleteGlobalRef(obj);
+ }
+
+ /** Wrapped JNI function. */
+ void PushLocalFrame(jint capacity) const
+ {
+ if (0 > m_env->PushLocalFrame(capacity))
+ throw_java_exception();
+ }
+
+ /** Wrapped JNI function. */
+ void PopLocalFrame() const throw()
+ {
+ m_env->PopLocalFrame(NULL);
+ }
+
+ /** Wrapped JNI function. */
+ jint Throw(jthrowable exc) const throw()
+ {
+ return m_env->Throw(exc);
+ }
+
+ /** Wrapped JNI function. */
+ jint ThrowNew(jclass cls, const char* message) const throw()
+ {
+ return m_env->ThrowNew(cls, message);
+ }
+
+ /** Wrapped JNI function. */
+ jboolean ExceptionCheck() const throw()
+ {
+ return m_env->ExceptionCheck();
+ }
+
+ /** Wrapped JNI function. */
+ jthrowable ExceptionOccurred() const throw()
+ {
+ return m_env->ExceptionOccurred();
+ }
+
+ /** Wrapped JNI function. */
+ void ExceptionClear() const throw()
+ {
+ m_env->ExceptionClear();
+ }
+
+ /** Wrapped JNI function. */
+ jclass FindClass(const char* name) const
+ {
+ jclass cls = m_env->FindClass(name);
+ check_java_exception();
+ return cls;
+ }
+
+ /** Wrapped JNI function. */
+ jobject NewObject(jclass cls, jmethodID ctor, ...) const
+ {
+ std::va_list args;
+ va_start(args, ctor);
+ jobject obj = m_env->NewObjectV(cls, ctor, args);
+ va_end(args);
+ check_java_exception();
+ return obj;
+ }
+
+ /** Wrapped JNI function. */
+ jclass GetObjectClass(jobject obj) const
+ {
+ jclass cls = m_env->GetObjectClass(obj);
+ check_java_exception();
+ return cls;
+ }
+
+ /** Wrapped JNI function. */
+ jboolean IsInstanceOf(jobject obj, jclass cls) const throw()
+ {
+ return m_env->IsInstanceOf(obj, cls);
+ }
+
+ /** Wrapped JNI function. */
+ jmethodID GetMethodID(jclass cls, const char* name, const char* sig) const
+ {
+ jmethodID mid = m_env->GetMethodID(cls, name, sig);
+ check_java_exception();
+ return mid;
+ }
+
+ /** Wrapped JNI function. */
+ jmethodID GetStaticMethodID(jclass cls, const char* name,
+ const char* sig) const
+ {
+ jmethodID mid = m_env->GetStaticMethodID(cls, name, sig);
+ check_java_exception();
+ return mid;
+ }
+
+ /** Wrapped JNI function. */
+ jfieldID GetFieldID(jclass cls, const char* name, const char* sig) const
+ {
+ jfieldID fid = m_env->GetFieldID(cls, name, sig);
+ check_java_exception();
+ return fid;
+ }
+
+ /** Wrapped JNI function. */
+ jfieldID GetStaticFieldID(jclass cls, const char* name,
+ const char* sig) const
+ {
+ jfieldID fid = m_env->GetStaticFieldID(cls, name, sig);
+ check_java_exception();
+ return fid;
+ }
+
+ /** Wrapped JNI function. */
+ jstring NewStringUTF(const char* text) const
+ {
+ if (!text)
+ return NULL;
+
+ jstring str = m_env->NewStringUTF(text);
+ check_java_exception();
+ return str;
+ }
+
+ /** Wrapped JNI function. */
+ jsize GetStringLength(jstring str) const
+ {
+ jsize len = m_env->GetStringLength(str);
+ check_java_exception();
+ return len;
+ }
+
+ /** Wrapped JNI function. */
+ jsize GetStringUTFLength(jstring str) const
+ {
+ jsize len = m_env->GetStringUTFLength(str);
+ check_java_exception();
+ return len;
+ }
+
+ /** Wrapped JNI function. */
+ const char* GetStringUTFChars(jstring str, jboolean* is_copy) const
+ {
+ if (!str)
+ return NULL;
+
+ const char* text = m_env->GetStringUTFChars(str, is_copy);
+ check_java_exception();
+ if (!text)
+ throw_java_out_of_memory(error_get_contents_string());
+ return text;
+ }
+
+ /** Wrapped JNI function. */
+ void ReleaseStringUTFChars(jstring str, const char* new_text) const
+ {
+ if (!str)
+ throw std::logic_error(error_release_null_string());
+ m_env->ReleaseStringUTFChars(str, new_text);
+ }
+
+ /** Wrapped JNI function. */
+ void CallVoidMethod(jobject obj, jmethodID mid, ...) const
+ {
+ std::va_list args;
+ va_start(args, mid);
+ m_env->CallObjectMethodV(obj, mid, args);
+ va_end(args);
+ check_java_exception();
+ }
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(T, N) \
+ T Call##N##Method(jobject obj, jmethodID mid, ...) const \
+ { \
+ std::va_list args; \
+ va_start(args, mid); \
+ T ret = m_env->Call##N##MethodV(obj, mid, args); \
+ va_end(args); \
+ check_java_exception(); \
+ return ret; \
+ }
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_CALL_X_METHOD
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(T, N) \
+ T CallStatic##N##Method(jclass obj, jmethodID mid, ...) const \
+ { \
+ std::va_list args; \
+ va_start(args, mid); \
+ T ret = m_env->CallStatic##N##MethodV(obj, mid, args); \
+ va_end(args); \
+ check_java_exception(); \
+ return ret; \
+ }
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_CALL_STATIC_X_METHOD
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(T, N) \
+ T Get##N##Field(jobject obj, jfieldID fid) const \
+ { \
+ T ret = m_env->Get##N##Field(obj, fid); \
+ check_java_exception(); \
+ return ret; \
+ }
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_GET_X_FIELD
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(T, N) \
+ void Set##N##Field(jobject obj, jfieldID fid, T val) const \
+ { \
+ m_env->Set##N##Field(obj, fid, val); \
+ check_java_exception(); \
+ }
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_SET_X_FIELD
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(T, N) \
+ T GetStatic##N##Field(jclass cls, jfieldID fid) const \
+ { \
+ T ret = m_env->GetStatic##N##Field(cls, fid); \
+ check_java_exception(); \
+ return ret; \
+ }
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_GET_STATIC_X_FIELD
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(T, N) \
+ void SetStatic##N##Field(jclass cls, jfieldID fid, T val) const \
+ { \
+ m_env->SetStatic##N##Field(cls, fid, val); \
+ check_java_exception(); \
+ }
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jobject, Object)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_SET_STATIC_X_FIELD
+
+ /** Wrapped JNI function. */
+ jsize GetArrayLength(jarray array) const
+ {
+ if (!array)
+ return 0;
+ return m_env->GetArrayLength(array);
+ }
+
+ /** Wrapped JNI function. */
+ jobjectArray NewObjectArray(jsize length, jclass cls, jobject init) const
+ {
+ jobjectArray array = m_env->NewObjectArray(length, cls, init);
+ if (!array)
+ throw_java_out_of_memory(error_create_object_array());
+ return array;
+ }
+
+ /** Wrapped JNI function. */
+ jobject GetObjectArrayElement(jobjectArray array, jsize index) const
+ {
+ jobject obj = m_env->GetObjectArrayElement(array, index);
+ check_java_exception();
+ return obj;
+ }
+
+ /** Wrapped JNI function. */
+ void SetObjectArrayElement(jobjectArray array,
+ jsize index, jobject value) const
+ {
+ m_env->SetObjectArrayElement(array, index, value);
+ check_java_exception();
+ }
+
+ /** Boilerplate generator for wrapped JNI functions. */
+#define SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(T, N) \
+ T##Array New##N##Array(jsize length) const \
+ { \
+ T##Array array = m_env->New##N##Array(length); \
+ if (!array) \
+ throw_java_out_of_memory(error_create_array(#T)); \
+ return array; \
+ } \
+ T* Get##N##ArrayElements(T##Array array, jboolean* is_copy) const \
+ { \
+ if (!array) \
+ return NULL; \
+ \
+ T* data = m_env->Get##N##ArrayElements(array, is_copy); \
+ check_java_exception(); \
+ if (!data) \
+ throw_java_out_of_memory(error_get_contents_array(#N)); \
+ return data; \
+ } \
+ void Release##N##ArrayElements(T##Array array, T* data, jint mode) const \
+ { \
+ if (!array) \
+ throw std::logic_error(error_release_null_array(#T)); \
+ m_env->Release##N##ArrayElements(array, data, mode); \
+ }
+
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jboolean, Boolean)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jbyte, Byte)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jchar, Char)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jshort, Short)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jint, Int)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jlong, Long)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jfloat, Float)
+ SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY(jdouble, Double)
+#undef SVN_JAVAHL_JNIWRAPPER_PRIMITIVE_TYPE_ARRAY
+
+ /** Wrapped JNI function. */
+ void* GetDirectBufferAddress(jobject buffer) const
+ {
+ void* const addr = m_env->GetDirectBufferAddress(buffer);
+ check_java_exception();
+ return addr;
+ }
+
+private:
+ ::JNIEnv* m_env;
+ static ::JavaVM* m_jvm;
+ static ::JNIEnv* env_from_jvm();
+
+ void throw_java_exception() const
+ {
+ throw SignalExceptionThrown();
+ }
+
+ void check_java_exception() const
+ {
+ if (m_env->ExceptionCheck())
+ throw SignalExceptionThrown();
+ }
+
+ void throw_java_out_of_memory(const char* message) const;
+
+ // We cannont use svn_private_config.h in a header, so we move the
+ // actual message translations into the implementation file.
+ static const char* error_create_global_reference() throw();
+ static const char* error_get_contents_string() throw();
+ static const char* error_release_null_string() throw();
+
+ static const char* error_create_object_array() throw();
+ static const char* error_create_array(const char* type) throw();
+ static const char* error_get_contents_array(const char* type) throw();
+ static const char* error_release_null_array(const char* type) throw();
+
+public:
+ // This static initializer must only be called by JNI_OnLoad
+ static void static_init(::JavaVM*);
+};
+
+
+/**
+ * Encapsulation of a JNI local frame.
+ *
+ * Used within loop bodies to limit the proliferation of local
+ * references, or anywhere else where such references should be
+ * pre-emptively discarded.
+ *
+ * @since New in 1.9.
+ */
+class LocalFrame
+{
+ static const jint DEFAULT_CAPACITY;
+
+public:
+ /**
+ * Constructs a local frame, retrieving the JNI environment
+ * reference from the global JVM reference.
+ */
+ explicit LocalFrame()
+ : m_env(Env())
+ {
+ m_env.PushLocalFrame(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Given a JNI renvironment reference, constructs a local frame.
+ */
+ explicit LocalFrame(Env env)
+ : m_env(env)
+ {
+ m_env.PushLocalFrame(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Constructs a local frame with the given initial @a capacity,
+ * retrieving the JNI environment reference from the global JVM
+ * reference.
+ */
+ explicit LocalFrame(jint capacity)
+ : m_env(Env())
+ {
+ m_env.PushLocalFrame(capacity);
+ }
+
+ /**
+ * Given a JNI renvironment reference, constructs a local frame with
+ * the given initial @a capacity.
+ */
+ explicit LocalFrame(Env env, jint capacity)
+ : m_env(env)
+ {
+ m_env.PushLocalFrame(capacity);
+ }
+
+ ~LocalFrame()
+ {
+ m_env.PopLocalFrame();
+ }
+
+ /**
+ * Returns the stored enviromnent object.
+ */
+ Env get_env() const
+ {
+ return m_env;
+ }
+
+private:
+ const Env m_env;
+ LocalFrame(const LocalFrame&);
+ LocalFrame& operator=(const LocalFrame&);
+};
+
+} // namespace Java
+
+#endif // SVN_JAVAHL_JNIWRAPPER_ENV_HPP