1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * This file contains support for director classes that proxy
8 * method calls from C++ to Java extensions.
9 * ----------------------------------------------------------------------------- */
13 #if defined(DEBUG_DIRECTOR_OWNED)
18 /* Java object wrapper */
19 class JObjectWrapper {
21 JObjectWrapper() : jthis_(NULL), weak_global_(true) {
29 bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
31 weak_global_ = weak_global;
33 jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj));
34 #if defined(DEBUG_DIRECTOR_OWNED)
35 std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
39 #if defined(DEBUG_DIRECTOR_OWNED)
40 std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
46 jobject get(JNIEnv *jenv) const {
47 #if defined(DEBUG_DIRECTOR_OWNED)
48 std::cout << "JObjectWrapper::get(";
53 std::cout << ") -> return new local ref" << std::endl;
55 return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
58 void release(JNIEnv *jenv) {
59 #if defined(DEBUG_DIRECTOR_OWNED)
60 std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "weak global ref" : "global ref") << std::endl;
64 if (jenv->IsSameObject(jthis_, NULL) == JNI_FALSE)
65 jenv->DeleteWeakGlobalRef((jweak)jthis_);
67 jenv->DeleteGlobalRef(jthis_);
78 /* Java proxy releases ownership of C++ object, C++ object is now
79 responsible for destruction (creates NewGlobalRef to pin Java
81 void java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
82 if (take_or_release) { /* Java takes ownership of C++ object's lifetime. */
84 jenv->DeleteGlobalRef(jthis_);
85 jthis_ = jenv->NewWeakGlobalRef(jself);
88 } else { /* Java releases ownership of C++ object's lifetime */
90 jenv->DeleteWeakGlobalRef((jweak)jthis_);
91 jthis_ = jenv->NewGlobalRef(jself);
98 /* pointer to Java object */
100 /* Local or global reference flag */
104 /* director base class */
106 /* pointer to Java virtual machine */
110 #if defined (_MSC_VER) && (_MSC_VER<1300)
112 friend class JNIEnvWrapper;
114 /* Utility class for managing the JNI environment */
115 class JNIEnvWrapper {
116 const Director *director_;
119 JNIEnvWrapper(const Director *director) : director_(director), jenv_(0) {
120 #if defined(SWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON)
121 // Attach a daemon thread to the JVM. Useful when the JVM should not wait for
122 // the thread to exit upon shutdown. Only for jdk-1.4 and later.
123 director_->swig_jvm_->AttachCurrentThreadAsDaemon((void **) &jenv_, NULL);
125 director_->swig_jvm_->AttachCurrentThread((void **) &jenv_, NULL);
129 #if !defined(SWIG_JAVA_NO_DETACH_CURRENT_THREAD)
130 // Some JVMs, eg jdk-1.4.2 and lower on Solaris have a bug and crash with the DetachCurrentThread call.
131 // However, without this call, the JVM hangs on exit when the thread was not created by the JVM and creates a memory leak.
132 director_->swig_jvm_->DetachCurrentThread();
135 JNIEnv *getJNIEnv() const {
140 /* Java object wrapper */
141 JObjectWrapper swig_self_;
143 /* Disconnect director from Java object */
144 void swig_disconnect_director_self(const char *disconn_method) {
145 JNIEnvWrapper jnienv(this) ;
146 JNIEnv *jenv = jnienv.getJNIEnv() ;
147 jobject jobj = swig_self_.peek();
148 #if defined(DEBUG_DIRECTOR_OWNED)
149 std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
151 if (jobj && jenv->IsSameObject(jobj, NULL) == JNI_FALSE) {
152 jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
154 #if defined(DEBUG_DIRECTOR_OWNED)
155 std::cout << "Swig::Director::disconnect_director_self upcall to " << disconn_method << std::endl;
157 jenv->CallVoidMethod(jobj, disconn_meth);
163 Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() {
164 /* Acquire the Java VM pointer */
165 jenv->GetJavaVM(&swig_jvm_);
168 virtual ~Director() {
169 JNIEnvWrapper jnienv(this) ;
170 JNIEnv *jenv = jnienv.getJNIEnv() ;
171 swig_self_.release(jenv);
174 bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
175 return swig_self_.set(jenv, jself, mem_own, weak_global);
178 jobject swig_get_self(JNIEnv *jenv) const {
179 return swig_self_.get(jenv);
182 // Change C++ object's ownership, relative to Java
183 void swig_java_change_ownership(JNIEnv *jenv, jobject jself, bool take_or_release) {
184 swig_self_.java_change_ownership(jenv, jself, take_or_release);
189 #endif /* __cplusplus */