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