JDK-6590839 : JNI Spec should point out Java objects created in JNI using AllocObject are not finalized
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2007-08-08
  • Updated: 2015-06-02
  • Resolved: 2015-06-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Resolved
Related Reports
Duplicate :  
Relates :  
Description
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.

Comments
Merged into 8079466
02-06-2015

Reviewed: http://cr.openjdk.java.net/~dsimms/jnispec/6590839/ Assigned to tech writer: JDK-8042218
15-05-2014

So there is no code issue here as David Holmes points out the documentation is fairly concise. It would however be useful if JNI Specification text pertaining to "AllocObject()" pointed out this subtle difference with "NewObject()".
02-04-2014

To be eligible for finalization an object must be constructed - specifically the Object() constructor must complete successfully: "An object o is not finalizable until its constructor has invoked the constructor for Object on o and that invocation has completed successfully (that is, without throwing an exception)." http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.6.1 However AllocObject does not invoke any constructors: AllocObject jobject AllocObject(JNIEnv *env, jclass clazz); Allocates a new Java object without invoking any of the constructors for the object. http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#wp16337 --- Consequently an object allocated (not created) via AllocObject should not be finalized. If finalization is desired then a constructor for the object must be invoked.
20-03-2014

Please check the spec first. If non-compliant with the spec, also check if still reproducible.
19-03-2014