JNI - Object creation with incorrect constructor
David Holmes
david.holmes at oracle.com
Sun Mar 12 23:40:26 UTC 2017
On 13/03/2017 9:34 AM, Piotr Chmielewski wrote:
> Thanks for response, both Roger and David :)
>
> I imagine, it doesn't change anything when calling these function not
> from Java method marked with "native" keyword but from C/C++ when
> starting VM using Invocation API ?
No difference - it is all just C/C++ code using JNI to call back into
the JVM.
David
>
> On 11.03.2017 05:06, David Holmes wrote:
>> Hi Piotr,
>>
>> On 11/03/2017 1: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 ?
>>
>> By design. It is up the the programmer to use JNI correctly:
>>
>> http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html
>>
>>
>> "Reporting Programming Errors
>>
>> The JNI does not check for programming errors such as passing in NULL
>> pointers or illegal argument types. Illegal argument types includes
>> such things as using a normal Java object instead of a Java class
>> object. The JNI does not check for these programming errors for the
>> following reasons:
>>
>> Forcing JNI functions to check for all possible error conditions
>> degrades the performance of normal (correct) native methods.
>> In many cases, there is not enough runtime type information to
>> perform such checking.
>>
>> Most C library functions do not guard against programming errors. The
>> printf() function, for example, usually causes a runtime error, rather
>> than returning an error code, when it receives an invalid address.
>> Forcing C library functions to check for all possible error conditions
>> would likely result in such checks to be duplicated--once in the user
>> code, and then again in the library.
>>
>> The programmer must not pass illegal pointers or arguments of the
>> wrong type to JNI functions. Doing so could result in arbitrary
>> consequences, including a corrupted system state or VM crash."
>>
>> ----
>>
>> Note the last sentence in particular. :)
>>
>> Cheers,
>> David
>>
>
More information about the jdk9-dev
mailing list