Add documentation patch #1743573 from Jeffrey Sorensen about better memory management by the JVM of C++ allocated memory
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9894 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
3f0bbe1581
commit
6b412b1e86
2 changed files with 122 additions and 0 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
Version 1.3.32 (in progress)
|
Version 1.3.32 (in progress)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
08/10/2007: wsfulton
|
||||||
|
[Java] Add documentation patch #1743573 from Jeffrey Sorensen. It contains a neat
|
||||||
|
idea with respect to better memory management by the JVM of C++ allocated memory.
|
||||||
|
|
||||||
08/10/2007: wsfulton
|
08/10/2007: wsfulton
|
||||||
[Perl] Apply patch #1771410 from Wade Brainerd to fix typedef XS(SwigPerlWrapper) in
|
[Perl] Apply patch #1771410 from Wade Brainerd to fix typedef XS(SwigPerlWrapper) in
|
||||||
perlrun.swg for ActiveState Perl build 822 and Perl 5.8.9 and 5.10 branches.
|
perlrun.swg for ActiveState Perl build 822 and Perl 5.8.9 and 5.10 branches.
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
<li><a href="#simple_pointers">Simple pointers</a>
|
<li><a href="#simple_pointers">Simple pointers</a>
|
||||||
<li><a href="#c_arrays">Wrapping C arrays with Java arrays</a>
|
<li><a href="#c_arrays">Wrapping C arrays with Java arrays</a>
|
||||||
<li><a href="#unbounded_c_arrays">Unbounded C Arrays</a>
|
<li><a href="#unbounded_c_arrays">Unbounded C Arrays</a>
|
||||||
|
<li><a href="#java_heap_allocations">Overriding new and delete to allocate from Java heap</a>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#java_typemaps">Java typemaps</a>
|
<li><a href="#java_typemaps">Java typemaps</a>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
@ -4143,6 +4144,123 @@ well suited for applications in which you need to create buffers,
|
||||||
package binary data, etc.
|
package binary data, etc.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<H3><a name="java_heap_allocations"></a>20.7.5 Overriding new and delete to allocate from Java heap</H3>
|
||||||
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unlike some languages supported by SWIG, Java has a true garbage collection
|
||||||
|
subsystem. Other languages will free SWIG wrapped objects when their reference
|
||||||
|
count reaches zero. Java only schedules these objects for finalization, which
|
||||||
|
may not occur for some time. Because SWIG objects are allocated on the C
|
||||||
|
heap, Java users may find the JVM memory use
|
||||||
|
quickly exceeds the assigned limits, as memory fills with unfinalized proxy
|
||||||
|
objects. Forcing garbage collection is clearly an undesirable solution.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
An elegant fix for C++ users is to override new and delete using the following
|
||||||
|
code (here shown included in a SWIG interface file)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="code">
|
||||||
|
<pre>
|
||||||
|
/* File: java_heap.i */
|
||||||
|
%module test
|
||||||
|
%{
|
||||||
|
#include <stdexcept>
|
||||||
|
#include "jni.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stash area embedded in each allocation to hold java handles
|
||||||
|
*/
|
||||||
|
struct Jalloc {
|
||||||
|
jbyteArray jba;
|
||||||
|
jobject ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
static JavaVM *cached_jvm = 0;
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||||
|
cached_jvm = jvm;
|
||||||
|
return JNI_VERSION_1_2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static JNIEnv * JNU_GetEnv() {
|
||||||
|
JNIEnv *env;
|
||||||
|
jint rc = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_2);
|
||||||
|
if (rc == JNI_EDETACHED)
|
||||||
|
throw std::runtime_error("current thread not attached");
|
||||||
|
if (rc == JNI_EVERSION)
|
||||||
|
throw std::runtime_error("jni version not supported");
|
||||||
|
return env;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * operator new(size_t t) {
|
||||||
|
if (cached_jvm != 0) {
|
||||||
|
JNIEnv *env = JNU_GetEnv();
|
||||||
|
jbyteArray jba = env->NewByteArray((int) t + sizeof(Jalloc));
|
||||||
|
if (env->ExceptionOccurred())
|
||||||
|
throw bad_alloc();
|
||||||
|
void *jbuffer = static_cast<void *>(env->GetByteArrayElements(jba, 0));
|
||||||
|
if (env->ExceptionOccurred())
|
||||||
|
throw bad_alloc();
|
||||||
|
Jalloc *pJalloc = static_cast<Jalloc *>(jbuffer);
|
||||||
|
pJalloc->jba = jba;
|
||||||
|
/* Assign a global reference so byte array will persist until delete'ed */
|
||||||
|
pJalloc->ref = env->NewGlobalRef(jba);
|
||||||
|
if (env->ExceptionOccurred())
|
||||||
|
throw bad_alloc();
|
||||||
|
return static_cast<void *>(static_cast<char *>(jbuffer) + sizeof(Jalloc));
|
||||||
|
}
|
||||||
|
else { /* JNI_OnLoad not called, use malloc and mark as special */
|
||||||
|
Jalloc *pJalloc = static_cast<Jalloc *>(malloc((int) t + sizeof(Jalloc)));
|
||||||
|
if (!pJalloc)
|
||||||
|
throw bad_alloc();
|
||||||
|
pJalloc->ref = 0;
|
||||||
|
return static_cast<void *>(
|
||||||
|
static_cast<char *>(static_cast<void *>(pJalloc)) + sizeof(Jalloc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *v) {
|
||||||
|
if (v != 0) {
|
||||||
|
void *buffer = static_cast<void *>( static_cast<char *>(v) - sizeof(Jalloc));
|
||||||
|
Jalloc *pJalloc = static_cast<Jalloc *>(buffer);
|
||||||
|
if (pJalloc->ref) {
|
||||||
|
JNIEnv *env = JNU_GetEnv();
|
||||||
|
env->DeleteGlobalRef(pJalloc->ref);
|
||||||
|
env->ReleaseByteArrayElements(pJalloc->jba, static_cast<jbyte *>(buffer), 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This code caches the Java environment during initialization,
|
||||||
|
and when new is called, a Java ByteArray is allocated to provide the
|
||||||
|
SWIG objects with space in the Java heap. This has the combined
|
||||||
|
effect of re-asserting the Java virtual machine's limit on memory allocation,
|
||||||
|
and puts additional pressure on the garbage collection system to run more
|
||||||
|
frequently.
|
||||||
|
This code is made slightly more complicated because allowances must be made
|
||||||
|
if new is called before the JNI_OnLoad is executed. This can happen during
|
||||||
|
static class initialization, for example.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Unfortunately, because most Java implementations call malloc and free, this
|
||||||
|
solution will not work for C wrapped structures. However, you are free to
|
||||||
|
make functions that allocate and free memory from the Java heap using this
|
||||||
|
model and use these functions in place of malloc and free in your own
|
||||||
|
code.
|
||||||
|
</p>
|
||||||
|
|
||||||
<H2><a name="java_typemaps"></a>20.8 Java typemaps</H2>
|
<H2><a name="java_typemaps"></a>20.8 Java typemaps</H2>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue