JNI - Object creation with incorrect constructor

David Holmes david.holmes at oracle.com
Sat Mar 11 04:06:22 UTC 2017


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