FULL PRODUCT VERSION :
java version "1.6.0_01"
Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux matrix 2.6.15-gentoo-r1 #1 SMP Tue Mar 14 15:56:46 Local time zone must be set--see zic i686 Intel(R) Pentium(R) 4 CPU 3.20GHz GenuineIntel GNU/Linux
SunOS devsun1 5.8 Generic_108528-29 sun4u sparc SUNW,Sun-Blade-100
A DESCRIPTION OF THE PROBLEM :
Objects that are created in JNI using AllocObject never have finalize called on them. Because of this, finalize methods that clean up non-Java resources are never called, leading to memory leaks.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1) Create an object in JNI using AllocObject
2) Release the handle to that object in the VM
3) Force garbage-collection
4) Look for signs of finalization
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
In the test case below I expect to see some notification of finalization. In actual use our customers some times hold dynamically-created C++ objects in memory of objects we create this way, and lack of finalization
leads to memory leaks. We've been in production with this technique since JDK 1.1 and cannot easily support JDK 1.6 as currently implemented.
ACTUAL -
Below I saw no printout unless I explicitly called the constructor to create objec ts.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
***ClassA.java***
public class ClassA {
public void finalize() {
System.out.println("FINALIZE");
}
}
***Finalize_bug.cpp***
#include "Finalize_bug.h"
JNIEXPORT jobject JNICALL Java_Finalize_1bug_createObject (JNIEnv *env, jclass obj, jclass cls) {
return env->AllocObject(cls) ;
}
***Finalize_bug.h***
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Finalize_bug */
#ifndef _Included_Finalize_bug
#define _Included_Finalize_bug
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Finalize_bug
* Method: createObject
* Signature: (Ljava/lang/Class;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_Finalize_1bug_createObject
(JNIEnv *, jclass, jclass);
#ifdef __cplusplus
}
#endif
#endif
***Finalize_bug.java***
public class Finalize_bug {
private static native Object createObject(Class cls);
public static void main(String args[]) {
try {
System.loadLibrary("Finalize");
for (int i = 0; i < 1000; i++) {
// uncomment the following line to see a finalize call
//ClassA obj = new ClassA();
ClassA obj = (ClassA)createObject(Class.forName("ClassA"));
}
System.gc();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
***Makefile***
JDK_HOME = /net/objyhome/home1/cwalter/jdk1.6.0_01
INCLUDES = -I$(JDK_HOME)/include -I$(JDK_HOME)/include/linux
default :
g++ ${INCLUDES} -c Finalize_bug.cpp
g++ -shared -o libFinalize.so Finalize_bug.o
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Haven't found one yet that will work with all customers because we use this object creation methodology to override security in their class definitions as well as to create empty objects. We can ask them to change their class definitions to provide empty public constructors if they use JDK 1.6, but this could be difficult to achieve.