JNI - Object creation with incorrect constructor

Roger Riggs roger.riggs at oracle.com
Fri Mar 10 17:05:40 UTC 2017


Hi Piotr,

On 3/10/17 11:41 AM, Piotr Chmielewski wrote:
> Thanks for answer.
>
> To clarify:
>
> 1. Is it up to programmer to ensure correctness of type/constructor 
> match as there no checks to detect mismatch (I did not find any in 
> documentation) ?
yes, it is up to the programmer.
Only constructors of the type and its supertypes are allowed.
A constructor for a completely unrelated class should be flagged as an 
error.
But I have not checked this.

>
> 2. In presented example, was object actually partially constructed 
> because of my error and how Hotspot handled it ?
NewObject allocates the heap for the object and initializes each field 
to the 0/null value for the field.
So every field has a predefined value but with only the specified 
constructor (and super constructors)
being invoked not every field will have been assigned by a constructor.

$.02, Roger


>
>
> On 10.03.2017 16:55, Roger Riggs wrote:
>> Hi Piotr,
>>
>> Using JNI requires a quite a bit more care than the Java API, there 
>> are fewer checks
>> and guarantees.  Make sure you are calling the method/constructor you 
>> intend to.
>> What you are seeing is an artifact of JNI and the Hotspot 
>> implementation.
>> Double check all JNI code twice before using.
>>
>> $.02, Roger
>>
>>
>> On 3/10/17 10:23 AM, Piotr Chmielewski wrote:
>>> When working on code with JNI Invocation API, I stumbled upon 
>>> curious case.
>>>
>>> Following code describes use of incorrect constructor in type when 
>>> creating new object.
>>>
>>>
>>> JNIEnv* env = ...;
>>>
>>> jclass cls_Object = env->FindClass("java/lang/Object");
>>> jmethodID constructor_Object = 
>>> env->GetMethodID(cls_Object,"<init>","()V");
>>> jclass cls_Date = env->FindClass("java/util/Date");
>>> jmethodID method_Date_toString = 
>>> env->GetMethodID(cls_Date,"toString","()Ljava/lang/String;");
>>>
>>> jobject obj_Date = env->NewObject(cls_Date,constructor_Object);
>>> jobject obj_toString = 
>>> env->CallObjectMethod(obj_Date,method_Date_toString);
>>>
>>> jstring str = static_cast<jstring>(obj_toString);
>>> jsize length = env->GetStringLength(str);
>>> char* dateString = new char[length];
>>> jsize start = 0;
>>> env->GetStringUTFRegion(jvmStr,start,length,data);
>>> std::cout << "Date: " << dateString << std::endl;
>>> delete[] dateString;
>>>
>>>
>>> This code works and prints "Thu Jan 01 01:00:00 CET 1970".
>>>
>>> Looks like "valid?" Date object is created using Object constructor 
>>> - partially created object.
>>>
>>> To understand the behavior, I checked OpenJDK sources for HotSpot. 
>>> Implementation of "NewObject" allocates space for object and 
>>> executes method on allocated space.
>>>
>>> Additionally, based on sources of "java.util.Date", memory for 
>>> object "obj_Date" is allocated and its values are set to default 
>>> values. Date then uses field "long fastTime" in toString method. 
>>> This results as object was created with "new Date(0)" instead "new 
>>> Date()";
>>>
>>> Main question: Is it a bug or by design, constructor's jmethodID is 
>>> not checked to belong to type when creating object ?
>>>
>>
>



More information about the jdk9-dev mailing list