9 * published by the Free Software Foundation.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26
27 #include "precompiled.hpp"
28 #include "jni.h"
29 #include "jvm.h"
30 #include "ci/ciReplay.hpp"
31 #include "classfile/altHashing.hpp"
32 #include "classfile/classFileStream.hpp"
33 #include "classfile/classLoader.hpp"
34 #include "classfile/classLoadInfo.hpp"
35 #include "classfile/javaClasses.hpp"
36 #include "classfile/javaClasses.inline.hpp"
37 #include "classfile/javaThreadStatus.hpp"
38 #include "classfile/moduleEntry.hpp"
39 #include "classfile/modules.hpp"
40 #include "classfile/symbolTable.hpp"
41 #include "classfile/systemDictionary.hpp"
42 #include "classfile/vmClasses.hpp"
43 #include "classfile/vmSymbols.hpp"
44 #include "compiler/compiler_globals.hpp"
45 #include "gc/shared/collectedHeap.hpp"
46 #include "gc/shared/gcLocker.inline.hpp"
47 #include "gc/shared/stringdedup/stringDedup.hpp"
48 #include "interpreter/linkResolver.hpp"
49 #include "jfr/jfrEvents.hpp"
50 #include "jfr/support/jfrThreadId.hpp"
51 #include "logging/log.hpp"
52 #include "memory/allocation.hpp"
53 #include "memory/allocation.inline.hpp"
54 #include "memory/oopFactory.hpp"
55 #include "memory/resourceArea.hpp"
56 #include "memory/universe.hpp"
57 #include "oops/access.inline.hpp"
58 #include "oops/arrayOop.hpp"
59 #include "oops/instanceKlass.inline.hpp"
60 #include "oops/instanceOop.hpp"
61 #include "oops/klass.inline.hpp"
62 #include "oops/markWord.hpp"
63 #include "oops/method.hpp"
64 #include "oops/objArrayKlass.hpp"
65 #include "oops/objArrayOop.inline.hpp"
66 #include "oops/oop.inline.hpp"
67 #include "oops/symbol.hpp"
68 #include "oops/typeArrayKlass.hpp"
69 #include "oops/typeArrayOop.inline.hpp"
70 #include "prims/jniCheck.hpp"
71 #include "prims/jniExport.hpp"
72 #include "prims/jniFastGetField.hpp"
73 #include "prims/jvm_misc.hpp"
74 #include "prims/jvmtiExport.hpp"
75 #include "prims/jvmtiThreadState.hpp"
76 #include "runtime/atomic.hpp"
77 #include "runtime/fieldDescriptor.inline.hpp"
78 #include "runtime/handles.inline.hpp"
405 int modifiers = java_lang_reflect_Field::modifiers(reflected);
406
407 // Make sure class is initialized before handing id's out to fields
408 k1->initialize(CHECK_NULL);
409
410 // First check if this is a static field
411 if (modifiers & JVM_ACC_STATIC) {
412 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
413 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
414 assert(id != NULL, "corrupt Field object");
415 debug_only(id->set_is_static_field_id();)
416 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
417 ret = jfieldIDWorkaround::to_static_jfieldID(id);
418 return ret;
419 }
420
421 // The slot is the index of the field description in the field-array
422 // The jfieldID is the offset of the field within the object
423 // It may also have hash bits for k, if VerifyJNIFields is turned on.
424 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
425 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
426 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
427 return ret;
428 JNI_END
429
430
431 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
432 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
433
434 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
435 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
436
437 jobject ret = NULL;
438 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
439
440 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
441 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
442 oop reflection_method;
443 if (m->is_initializer()) {
444 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
445 } else {
446 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
447 }
448 ret = JNIHandles::make_local(THREAD, reflection_method);
449 return ret;
450 JNI_END
451
452 DT_RETURN_MARK_DECL(GetSuperclass, jclass
453 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
454
455 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
456 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
457
458 jclass obj = NULL;
459 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
460
461 oop mirror = JNIHandles::resolve_non_null(sub);
462 // primitive classes return NULL
463 if (java_lang_Class::is_primitive(mirror)) return NULL;
479 "java_super computation depends on interface, array, other super");
480 obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(THREAD, super->java_mirror());
481 return obj;
482 JNI_END
483
484 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
485 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super);
486
487 oop sub_mirror = JNIHandles::resolve_non_null(sub);
488 oop super_mirror = JNIHandles::resolve_non_null(super);
489 if (java_lang_Class::is_primitive(sub_mirror) ||
490 java_lang_Class::is_primitive(super_mirror)) {
491 jboolean ret = (sub_mirror == super_mirror);
492
493 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
494 return ret;
495 }
496 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
497 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
498 assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
499 jboolean ret = sub_klass->is_subtype_of(super_klass) ?
500 JNI_TRUE : JNI_FALSE;
501
502 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
503 return ret;
504 JNI_END
505
506
507 DT_RETURN_MARK_DECL(Throw, jint
508 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
509
510 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
511 HOTSPOT_JNI_THROW_ENTRY(env, obj);
512
513 jint ret = JNI_OK;
514 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
515
516 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
517 ShouldNotReachHere();
518 return 0; // Mute compiler.
519 JNI_END
520
521
783 }
784
785 friend class SignatureIterator; // so do_parameters_on can call do_type
786 void do_type(BasicType type) {
787 switch (type) {
788 // these are coerced to int when using va_arg
789 case T_BYTE:
790 case T_CHAR:
791 case T_SHORT:
792 case T_INT: push_int(va_arg(_ap, jint)); break;
793 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
794
795 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
796
797 case T_LONG: push_long(va_arg(_ap, jlong)); break;
798 // float is coerced to double w/ va_arg
799 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
800 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
801
802 case T_ARRAY:
803 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
804 default: ShouldNotReachHere();
805 }
806 }
807
808 public:
809 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
810 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
811 set_ap(rap);
812 }
813
814 ~JNI_ArgumentPusherVaArg() {
815 va_end(_ap);
816 }
817
818 virtual void push_arguments_on(JavaCallArguments* arguments) {
819 _arguments = arguments;
820 do_parameters_on(this);
821 }
822 };
823
824
825 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
826 protected:
827 const jvalue *_ap;
828
829 inline void set_ap(const jvalue *rap) { _ap = rap; }
830
831 friend class SignatureIterator; // so do_parameters_on can call do_type
832 void do_type(BasicType type) {
833 switch (type) {
834 case T_CHAR: push_int((_ap++)->c); break;
835 case T_SHORT: push_int((_ap++)->s); break;
836 case T_BYTE: push_int((_ap++)->b); break;
837 case T_INT: push_int((_ap++)->i); break;
838 case T_BOOLEAN: push_boolean((_ap++)->z); break;
839 case T_LONG: push_long((_ap++)->j); break;
840 case T_FLOAT: push_float((_ap++)->f); break;
841 case T_DOUBLE: push_double((_ap++)->d); break;
842 case T_ARRAY:
843 case T_OBJECT: push_object((_ap++)->l); break;
844 default: ShouldNotReachHere();
845 }
846 }
847
848 public:
849 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
850 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
851 set_ap(rap);
852 }
853
854 virtual void push_arguments_on(JavaCallArguments* arguments) {
855 _arguments = arguments;
856 do_parameters_on(this);
857 }
858 };
859
860
861 enum JNICallType {
862 JNI_STATIC,
863 JNI_VIRTUAL,
959 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
960 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
961
962 jobject ret = NULL;
963 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
964
965 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
966 ret = JNIHandles::make_local(THREAD, i);
967 return ret;
968 JNI_END
969
970 DT_RETURN_MARK_DECL(NewObjectA, jobject
971 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
972
973 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
974 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
975
976 jobject obj = NULL;
977 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
978
979 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
980 obj = JNIHandles::make_local(THREAD, i);
981 JavaValue jvalue(T_VOID);
982 JNI_ArgumentPusherArray ap(methodID, args);
983 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
984 return obj;
985 JNI_END
986
987
988 DT_RETURN_MARK_DECL(NewObjectV, jobject
989 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
990
991 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
992 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
993
994 jobject obj = NULL;
995 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
996
997 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
998 obj = JNIHandles::make_local(THREAD, i);
999 JavaValue jvalue(T_VOID);
1000 JNI_ArgumentPusherVaArg ap(methodID, args);
1001 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1002 return obj;
1003 JNI_END
1004
1005
1006 DT_RETURN_MARK_DECL(NewObject, jobject
1007 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1008
1009 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1010 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1011
1012 jobject obj = NULL;
1013 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1014
1015 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1016 obj = JNIHandles::make_local(THREAD, i);
1017 va_list args;
1018 va_start(args, methodID);
1019 JavaValue jvalue(T_VOID);
1020 JNI_ArgumentPusherVaArg ap(methodID, args);
1021 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1022 va_end(args);
1023 return obj;
1024 JNI_END
1025
1026
1027 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1028 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1029
1030 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1031 jclass ret =
1032 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1033
1034 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1035 return ret;
1036 JNI_END
1037
1038 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1039 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1040
1041 jboolean ret = JNI_TRUE;
1042 if (obj != NULL) {
1753 // table. If they're not there, the field doesn't exist.
1754 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1755 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1756 if (fieldname == NULL || signame == NULL) {
1757 ResourceMark rm;
1758 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1759 }
1760
1761 // Make sure class is initialized before handing id's out to fields
1762 k->initialize(CHECK_NULL);
1763
1764 fieldDescriptor fd;
1765 if (!k->is_instance_klass() ||
1766 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1767 ResourceMark rm;
1768 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1769 }
1770
1771 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1772 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1773 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1774 return ret;
1775 JNI_END
1776
1777
1778 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1779 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1780 oop o = JNIHandles::resolve_non_null(obj);
1781 Klass* k = o->klass();
1782 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1783 // Keep JVMTI addition small and only check enabled flag here.
1784 // jni_GetField_probe() assumes that is okay to create handles.
1785 if (JvmtiExport::should_post_field_access()) {
1786 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1787 }
1788 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1789 jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
1790 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1791 return ret;
1792 JNI_END
1793
1794
1795
1796 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1797 , EntryProbe, ReturnProbe) \
1798 \
1799 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1800 , ReturnProbe); \
1801 \
1802 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1803 \
1804 EntryProbe; \
1805 Return ret = 0;\
1806 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1807 \
1808 oop o = JNIHandles::resolve_non_null(obj); \
1809 Klass* k = o->klass(); \
1861 return (address)jni_GetLongField;
1862 }
1863 address jni_GetFloatField_addr() {
1864 return (address)jni_GetFloatField;
1865 }
1866 address jni_GetDoubleField_addr() {
1867 return (address)jni_GetDoubleField;
1868 }
1869
1870 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1871 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1872 oop o = JNIHandles::resolve_non_null(obj);
1873 Klass* k = o->klass();
1874 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1875 // Keep JVMTI addition small and only check enabled flag here.
1876 if (JvmtiExport::should_post_field_modification()) {
1877 jvalue field_value;
1878 field_value.l = value;
1879 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1880 }
1881 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1882 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1883 JNI_END
1884
1885
1886 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1887 , EntryProbe, ReturnProbe) \
1888 \
1889 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1890 \
1891 EntryProbe; \
1892 \
1893 oop o = JNIHandles::resolve_non_null(obj); \
1894 Klass* k = o->klass(); \
1895 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1896 /* Keep JVMTI addition small and only check enabled flag here. */ \
1897 if (JvmtiExport::should_post_field_modification()) { \
1898 jvalue field_value; \
1899 field_value.unionType = value; \
1900 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
1901 } \
2278 Klass* ak = ek->array_klass(CHECK_NULL);
2279 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2280 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2281 oop initial_value = JNIHandles::resolve(initialElement);
2282 if (initial_value != NULL) { // array already initialized with NULL
2283 for (int index = 0; index < length; index++) {
2284 result->obj_at_put(index, initial_value);
2285 }
2286 }
2287 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2288 return ret;
2289 JNI_END
2290
2291 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2292 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2293
2294 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2295 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2296 jobject ret = NULL;
2297 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2298 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2299 if (a->is_within_bounds(index)) {
2300 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2301 return ret;
2302 } else {
2303 ResourceMark rm(THREAD);
2304 stringStream ss;
2305 ss.print("Index %d out of bounds for length %d", index, a->length());
2306 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2307 }
2308 JNI_END
2309
2310 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2311 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2312
2313 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2314 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2315 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2316
2317 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2318 oop v = JNIHandles::resolve(value);
2319 if (a->is_within_bounds(index)) {
2320 if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2321 a->obj_at_put(index, v);
2322 } else {
2323 ResourceMark rm(THREAD);
2324 stringStream ss;
2325 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2326 ss.print("type mismatch: can not store %s to %s[%d]",
2327 v->klass()->external_name(),
2328 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2329 index);
2330 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2331 ss.print("[]");
2332 }
2333 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2334 }
2335 } else {
2336 ResourceMark rm(THREAD);
2337 stringStream ss;
2338 ss.print("Index %d out of bounds for length %d", index, a->length());
2339 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2340 }
2341 JNI_END
2342
2343
2344
2345 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2346 ,EntryProbe,ReturnProbe) \
2347 \
2348 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2349 , ReturnProbe); \
2350 \
2351 JNI_ENTRY(Return, \
2352 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2353 EntryProbe; \
2354 Return ret = NULL;\
2355 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2356 \
2357 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2358 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2359 return ret;\
2360 JNI_END
3116 JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))
3117 HOTSPOT_JNI_GETVERSION_ENTRY(env);
3118 HOTSPOT_JNI_GETVERSION_RETURN(CurrentVersion);
3119 return CurrentVersion;
3120 JNI_END
3121
3122 extern struct JavaVM_ main_vm;
3123
3124 JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))
3125 HOTSPOT_JNI_GETJAVAVM_ENTRY(env, (void **) vm);
3126 *vm = (JavaVM *)(&main_vm);
3127 HOTSPOT_JNI_GETJAVAVM_RETURN(JNI_OK);
3128 return JNI_OK;
3129 JNI_END
3130
3131
3132 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3133 return Modules::get_module(clazz, THREAD);
3134 JNI_END
3135
3136
3137 // Structure containing all jni functions
3138 struct JNINativeInterface_ jni_NativeInterface = {
3139 NULL,
3140 NULL,
3141 NULL,
3142
3143 NULL,
3144
3145 jni_GetVersion,
3146
3147 jni_DefineClass,
3148 jni_FindClass,
3149
3150 jni_FromReflectedMethod,
3151 jni_FromReflectedField,
3152
3153 jni_ToReflectedMethod,
3154
3155 jni_GetSuperclass,
3156 jni_IsAssignableFrom,
3400 jni_ReleasePrimitiveArrayCritical,
3401
3402 jni_GetStringCritical,
3403 jni_ReleaseStringCritical,
3404
3405 jni_NewWeakGlobalRef,
3406 jni_DeleteWeakGlobalRef,
3407
3408 jni_ExceptionCheck,
3409
3410 jni_NewDirectByteBuffer,
3411 jni_GetDirectBufferAddress,
3412 jni_GetDirectBufferCapacity,
3413
3414 // New 1_6 features
3415
3416 jni_GetObjectRefType,
3417
3418 // Module features
3419
3420 jni_GetModule
3421 };
3422
3423
3424 // For jvmti use to modify jni function table.
3425 // Java threads in native contiues to run until it is transitioned
3426 // to VM at safepoint. Before the transition or before it is blocked
3427 // for safepoint it may access jni function table. VM could crash if
3428 // any java thread access the jni function table in the middle of memcpy.
3429 // To avoid this each function pointers are copied automically.
3430 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3431 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3432 intptr_t *a = (intptr_t *) jni_functions();
3433 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3434 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3435 Atomic::store(a++, *b++);
3436 }
3437 }
3438
3439 void quicken_jni_functions() {
3440 // Replace Get<Primitive>Field with fast versions
|
9 * published by the Free Software Foundation.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 *
25 */
26
27 #include "precompiled.hpp"
28 #include "jni.h"
29 #include "jni.h"
30 #include "jvm.h"
31 #include "ci/ciReplay.hpp"
32 #include "classfile/altHashing.hpp"
33 #include "classfile/classFileStream.hpp"
34 #include "classfile/classLoader.hpp"
35 #include "classfile/classLoadInfo.hpp"
36 #include "classfile/javaClasses.hpp"
37 #include "classfile/javaClasses.inline.hpp"
38 #include "classfile/javaThreadStatus.hpp"
39 #include "classfile/moduleEntry.hpp"
40 #include "classfile/modules.hpp"
41 #include "classfile/symbolTable.hpp"
42 #include "classfile/systemDictionary.hpp"
43 #include "classfile/vmClasses.hpp"
44 #include "classfile/vmSymbols.hpp"
45 #include "compiler/compiler_globals.hpp"
46 #include "gc/shared/collectedHeap.hpp"
47 #include "gc/shared/gcLocker.inline.hpp"
48 #include "gc/shared/stringdedup/stringDedup.hpp"
49 #include "interpreter/linkResolver.hpp"
50 #include "jfr/jfrEvents.hpp"
51 #include "jfr/support/jfrThreadId.hpp"
52 #include "logging/log.hpp"
53 #include "memory/allocation.hpp"
54 #include "memory/allocation.inline.hpp"
55 #include "memory/oopFactory.hpp"
56 #include "memory/resourceArea.hpp"
57 #include "memory/universe.hpp"
58 #include "oops/access.inline.hpp"
59 #include "oops/arrayOop.hpp"
60 #include "oops/flatArrayOop.inline.hpp"
61 #include "oops/inlineKlass.inline.hpp"
62 #include "oops/instanceKlass.inline.hpp"
63 #include "oops/instanceOop.hpp"
64 #include "oops/klass.inline.hpp"
65 #include "oops/markWord.hpp"
66 #include "oops/method.hpp"
67 #include "oops/objArrayKlass.hpp"
68 #include "oops/objArrayOop.inline.hpp"
69 #include "oops/oop.inline.hpp"
70 #include "oops/symbol.hpp"
71 #include "oops/typeArrayKlass.hpp"
72 #include "oops/typeArrayOop.inline.hpp"
73 #include "prims/jniCheck.hpp"
74 #include "prims/jniExport.hpp"
75 #include "prims/jniFastGetField.hpp"
76 #include "prims/jvm_misc.hpp"
77 #include "prims/jvmtiExport.hpp"
78 #include "prims/jvmtiThreadState.hpp"
79 #include "runtime/atomic.hpp"
80 #include "runtime/fieldDescriptor.inline.hpp"
81 #include "runtime/handles.inline.hpp"
408 int modifiers = java_lang_reflect_Field::modifiers(reflected);
409
410 // Make sure class is initialized before handing id's out to fields
411 k1->initialize(CHECK_NULL);
412
413 // First check if this is a static field
414 if (modifiers & JVM_ACC_STATIC) {
415 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
416 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
417 assert(id != NULL, "corrupt Field object");
418 debug_only(id->set_is_static_field_id();)
419 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
420 ret = jfieldIDWorkaround::to_static_jfieldID(id);
421 return ret;
422 }
423
424 // The slot is the index of the field description in the field-array
425 // The jfieldID is the offset of the field within the object
426 // It may also have hash bits for k, if VerifyJNIFields is turned on.
427 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
428 bool is_inlined = InstanceKlass::cast(k1)->field_is_inlined(slot);
429 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
430 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_inlined);
431 return ret;
432 JNI_END
433
434
435 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
436 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
437
438 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
439 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
440
441 jobject ret = NULL;
442 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
443
444 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
445 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
446 oop reflection_method;
447 if (m->is_object_constructor() || m->is_static_init_factory()) {
448 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
449 } else {
450 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
451 }
452 ret = JNIHandles::make_local(THREAD, reflection_method);
453 return ret;
454 JNI_END
455
456 DT_RETURN_MARK_DECL(GetSuperclass, jclass
457 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
458
459 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
460 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
461
462 jclass obj = NULL;
463 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
464
465 oop mirror = JNIHandles::resolve_non_null(sub);
466 // primitive classes return NULL
467 if (java_lang_Class::is_primitive(mirror)) return NULL;
483 "java_super computation depends on interface, array, other super");
484 obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(THREAD, super->java_mirror());
485 return obj;
486 JNI_END
487
488 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
489 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super);
490
491 oop sub_mirror = JNIHandles::resolve_non_null(sub);
492 oop super_mirror = JNIHandles::resolve_non_null(super);
493 if (java_lang_Class::is_primitive(sub_mirror) ||
494 java_lang_Class::is_primitive(super_mirror)) {
495 jboolean ret = (sub_mirror == super_mirror);
496
497 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
498 return ret;
499 }
500 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
501 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
502 assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
503 jboolean ret;
504 if (sub_klass == super_klass && sub_klass->is_inline_klass()) {
505 // val type is a subtype of ref type
506 InlineKlass* ik = InlineKlass::cast(sub_klass);
507 if (sub_mirror == super_mirror || (ik->val_mirror() == sub_mirror && ik->ref_mirror() == super_mirror)) {
508 ret = JNI_TRUE;
509 } else {
510 ret = JNI_FALSE;
511 }
512 } else {
513 ret = sub_klass->is_subtype_of(super_klass) ? JNI_TRUE : JNI_FALSE;
514 }
515 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
516 return ret;
517 JNI_END
518
519
520 DT_RETURN_MARK_DECL(Throw, jint
521 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
522
523 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
524 HOTSPOT_JNI_THROW_ENTRY(env, obj);
525
526 jint ret = JNI_OK;
527 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
528
529 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
530 ShouldNotReachHere();
531 return 0; // Mute compiler.
532 JNI_END
533
534
796 }
797
798 friend class SignatureIterator; // so do_parameters_on can call do_type
799 void do_type(BasicType type) {
800 switch (type) {
801 // these are coerced to int when using va_arg
802 case T_BYTE:
803 case T_CHAR:
804 case T_SHORT:
805 case T_INT: push_int(va_arg(_ap, jint)); break;
806 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
807
808 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
809
810 case T_LONG: push_long(va_arg(_ap, jlong)); break;
811 // float is coerced to double w/ va_arg
812 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
813 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
814
815 case T_ARRAY:
816 case T_OBJECT:
817 case T_PRIMITIVE_OBJECT: push_object(va_arg(_ap, jobject)); break;
818 default: ShouldNotReachHere();
819 }
820 }
821
822 public:
823 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
824 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
825 set_ap(rap);
826 }
827
828 ~JNI_ArgumentPusherVaArg() {
829 va_end(_ap);
830 }
831
832 virtual void push_arguments_on(JavaCallArguments* arguments) {
833 _arguments = arguments;
834 do_parameters_on(this);
835 }
836 };
837
838
839 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
840 protected:
841 const jvalue *_ap;
842
843 inline void set_ap(const jvalue *rap) { _ap = rap; }
844
845 friend class SignatureIterator; // so do_parameters_on can call do_type
846 void do_type(BasicType type) {
847 switch (type) {
848 case T_CHAR: push_int((_ap++)->c); break;
849 case T_SHORT: push_int((_ap++)->s); break;
850 case T_BYTE: push_int((_ap++)->b); break;
851 case T_INT: push_int((_ap++)->i); break;
852 case T_BOOLEAN: push_boolean((_ap++)->z); break;
853 case T_LONG: push_long((_ap++)->j); break;
854 case T_FLOAT: push_float((_ap++)->f); break;
855 case T_DOUBLE: push_double((_ap++)->d); break;
856 case T_ARRAY:
857 case T_OBJECT:
858 case T_PRIMITIVE_OBJECT: push_object((_ap++)->l); break;
859 default: ShouldNotReachHere();
860 }
861 }
862
863 public:
864 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
865 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
866 set_ap(rap);
867 }
868
869 virtual void push_arguments_on(JavaCallArguments* arguments) {
870 _arguments = arguments;
871 do_parameters_on(this);
872 }
873 };
874
875
876 enum JNICallType {
877 JNI_STATIC,
878 JNI_VIRTUAL,
974 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
975 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
976
977 jobject ret = NULL;
978 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
979
980 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
981 ret = JNIHandles::make_local(THREAD, i);
982 return ret;
983 JNI_END
984
985 DT_RETURN_MARK_DECL(NewObjectA, jobject
986 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
987
988 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
989 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
990
991 jobject obj = NULL;
992 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
993
994 oop clazzoop = JNIHandles::resolve_non_null(clazz);
995 Klass* k = java_lang_Class::as_Klass(clazzoop);
996 if (k == NULL) {
997 ResourceMark rm(THREAD);
998 THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
999 }
1000
1001 if (!k->is_inline_klass()) {
1002 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1003 obj = JNIHandles::make_local(THREAD, i);
1004 JavaValue jvalue(T_VOID);
1005 JNI_ArgumentPusherArray ap(methodID, args);
1006 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1007 } else {
1008 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1009 JNI_ArgumentPusherArray ap(methodID, args);
1010 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
1011 obj = jvalue.get_jobject();
1012 }
1013 return obj;
1014 JNI_END
1015
1016
1017 DT_RETURN_MARK_DECL(NewObjectV, jobject
1018 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1019
1020 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1021 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1022
1023 jobject obj = NULL;
1024 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1025
1026 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1027 Klass* k = java_lang_Class::as_Klass(clazzoop);
1028 if (k == NULL) {
1029 ResourceMark rm(THREAD);
1030 THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
1031 }
1032
1033 if (!k->is_inline_klass()) {
1034 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1035 obj = JNIHandles::make_local(THREAD, i);
1036 JavaValue jvalue(T_VOID);
1037 JNI_ArgumentPusherVaArg ap(methodID, args);
1038 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1039 } else {
1040 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1041 JNI_ArgumentPusherVaArg ap(methodID, args);
1042 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
1043 obj = jvalue.get_jobject();
1044 }
1045 return obj;
1046 JNI_END
1047
1048
1049 DT_RETURN_MARK_DECL(NewObject, jobject
1050 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1051
1052 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1053 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1054
1055 jobject obj = NULL;
1056 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1057
1058 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1059 Klass* k = java_lang_Class::as_Klass(clazzoop);
1060 if (k == NULL) {
1061 ResourceMark rm(THREAD);
1062 THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
1063 }
1064
1065 if (!k->is_inline_klass()) {
1066 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1067 obj = JNIHandles::make_local(THREAD, i);
1068 va_list args;
1069 va_start(args, methodID);
1070 JavaValue jvalue(T_VOID);
1071 JNI_ArgumentPusherVaArg ap(methodID, args);
1072 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1073 va_end(args);
1074 } else {
1075 va_list args;
1076 va_start(args, methodID);
1077 JavaValue jvalue(T_PRIMITIVE_OBJECT);
1078 JNI_ArgumentPusherVaArg ap(methodID, args);
1079 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_NULL);
1080 va_end(args);
1081 obj = jvalue.get_jobject();
1082 }
1083 return obj;
1084 JNI_END
1085
1086
1087 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1088 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1089
1090 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1091 jclass ret =
1092 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1093
1094 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1095 return ret;
1096 JNI_END
1097
1098 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1099 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1100
1101 jboolean ret = JNI_TRUE;
1102 if (obj != NULL) {
1813 // table. If they're not there, the field doesn't exist.
1814 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1815 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1816 if (fieldname == NULL || signame == NULL) {
1817 ResourceMark rm;
1818 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1819 }
1820
1821 // Make sure class is initialized before handing id's out to fields
1822 k->initialize(CHECK_NULL);
1823
1824 fieldDescriptor fd;
1825 if (!k->is_instance_klass() ||
1826 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1827 ResourceMark rm;
1828 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1829 }
1830
1831 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1832 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1833 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_inlined());
1834 return ret;
1835 JNI_END
1836
1837
1838 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1839 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1840 oop o = JNIHandles::resolve_non_null(obj);
1841 Klass* k = o->klass();
1842 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1843 oop res = NULL;
1844 // Keep JVMTI addition small and only check enabled flag here.
1845 // jni_GetField_probe() assumes that is okay to create handles.
1846 if (JvmtiExport::should_post_field_access()) {
1847 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1848 }
1849 if (!jfieldIDWorkaround::is_inlined_jfieldID(fieldID)) {
1850 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1851 } else {
1852 assert(k->is_instance_klass(), "Only instance can have inlined fields");
1853 InstanceKlass* ik = InstanceKlass::cast(k);
1854 fieldDescriptor fd;
1855 ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1856 InstanceKlass* holder = fd.field_holder();
1857 InlineKlass* field_vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1858 res = field_vklass->read_inlined_field(o, ik->field_offset(fd.index()), CHECK_NULL);
1859 }
1860 jobject ret = JNIHandles::make_local(THREAD, res);
1861 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1862 return ret;
1863 JNI_END
1864
1865
1866
1867 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1868 , EntryProbe, ReturnProbe) \
1869 \
1870 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1871 , ReturnProbe); \
1872 \
1873 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1874 \
1875 EntryProbe; \
1876 Return ret = 0;\
1877 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1878 \
1879 oop o = JNIHandles::resolve_non_null(obj); \
1880 Klass* k = o->klass(); \
1932 return (address)jni_GetLongField;
1933 }
1934 address jni_GetFloatField_addr() {
1935 return (address)jni_GetFloatField;
1936 }
1937 address jni_GetDoubleField_addr() {
1938 return (address)jni_GetDoubleField;
1939 }
1940
1941 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1942 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1943 oop o = JNIHandles::resolve_non_null(obj);
1944 Klass* k = o->klass();
1945 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1946 // Keep JVMTI addition small and only check enabled flag here.
1947 if (JvmtiExport::should_post_field_modification()) {
1948 jvalue field_value;
1949 field_value.l = value;
1950 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1951 }
1952 if (!jfieldIDWorkaround::is_inlined_jfieldID(fieldID)) {
1953 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1954 } else {
1955 assert(k->is_instance_klass(), "Only instances can have inlined fields");
1956 InstanceKlass* ik = InstanceKlass::cast(k);
1957 fieldDescriptor fd;
1958 ik->find_field_from_offset(offset, false, &fd);
1959 InstanceKlass* holder = fd.field_holder();
1960 InlineKlass* vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1961 oop v = JNIHandles::resolve_non_null(value);
1962 vklass->write_inlined_field(o, offset, v, CHECK);
1963 }
1964 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1965 JNI_END
1966
1967
1968 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1969 , EntryProbe, ReturnProbe) \
1970 \
1971 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1972 \
1973 EntryProbe; \
1974 \
1975 oop o = JNIHandles::resolve_non_null(obj); \
1976 Klass* k = o->klass(); \
1977 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1978 /* Keep JVMTI addition small and only check enabled flag here. */ \
1979 if (JvmtiExport::should_post_field_modification()) { \
1980 jvalue field_value; \
1981 field_value.unionType = value; \
1982 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
1983 } \
2360 Klass* ak = ek->array_klass(CHECK_NULL);
2361 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2362 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2363 oop initial_value = JNIHandles::resolve(initialElement);
2364 if (initial_value != NULL) { // array already initialized with NULL
2365 for (int index = 0; index < length; index++) {
2366 result->obj_at_put(index, initial_value);
2367 }
2368 }
2369 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2370 return ret;
2371 JNI_END
2372
2373 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2374 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2375
2376 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2377 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2378 jobject ret = NULL;
2379 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2380 oop res = NULL;
2381 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2382 if (arr->is_within_bounds(index)) {
2383 if (arr->is_flatArray()) {
2384 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2385 flatArrayHandle vah(thread, a);
2386 res = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK_NULL);
2387 assert(res != NULL, "Must be set in one of two paths above");
2388 } else {
2389 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2390 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2391 res = a->obj_at(index);
2392 }
2393 } else {
2394 ResourceMark rm(THREAD);
2395 stringStream ss;
2396 ss.print("Index %d out of bounds for length %d", index,arr->length());
2397 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2398 }
2399 ret = JNIHandles::make_local(THREAD, res);
2400 return ret;
2401 JNI_END
2402
2403 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2404 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2405
2406 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2407 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2408 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2409
2410 bool oob = false;
2411 int length = -1;
2412 oop res = NULL;
2413 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2414 if (arr->is_within_bounds(index)) {
2415 if (arr->is_flatArray()) {
2416 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2417 oop v = JNIHandles::resolve(value);
2418 FlatArrayKlass* vaklass = FlatArrayKlass::cast(a->klass());
2419 InlineKlass* element_vklass = vaklass->element_klass();
2420 if (v != NULL && v->is_a(element_vklass)) {
2421 a->value_copy_to_index(v, index);
2422 } else {
2423 ResourceMark rm(THREAD);
2424 stringStream ss;
2425 Klass *kl = FlatArrayKlass::cast(a->klass());
2426 ss.print("type mismatch: can not store %s to %s[%d]",
2427 v->klass()->external_name(),
2428 kl->external_name(),
2429 index);
2430 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2431 ss.print("[]");
2432 }
2433 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2434 }
2435 } else {
2436 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2437 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2438 oop v = JNIHandles::resolve(value);
2439 if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2440 a->obj_at_put(index, v);
2441 } else {
2442 ResourceMark rm(THREAD);
2443 stringStream ss;
2444 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2445 ss.print("type mismatch: can not store %s to %s[%d]",
2446 v->klass()->external_name(),
2447 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2448 index);
2449 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2450 ss.print("[]");
2451 }
2452 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2453 }
2454 }
2455 } else {
2456 ResourceMark rm(THREAD);
2457 stringStream ss;
2458 ss.print("Index %d out of bounds for length %d", index, arr->length());
2459 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2460 }
2461 JNI_END
2462
2463
2464
2465 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2466 ,EntryProbe,ReturnProbe) \
2467 \
2468 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2469 , ReturnProbe); \
2470 \
2471 JNI_ENTRY(Return, \
2472 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2473 EntryProbe; \
2474 Return ret = NULL;\
2475 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2476 \
2477 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2478 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2479 return ret;\
2480 JNI_END
3236 JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))
3237 HOTSPOT_JNI_GETVERSION_ENTRY(env);
3238 HOTSPOT_JNI_GETVERSION_RETURN(CurrentVersion);
3239 return CurrentVersion;
3240 JNI_END
3241
3242 extern struct JavaVM_ main_vm;
3243
3244 JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))
3245 HOTSPOT_JNI_GETJAVAVM_ENTRY(env, (void **) vm);
3246 *vm = (JavaVM *)(&main_vm);
3247 HOTSPOT_JNI_GETJAVAVM_RETURN(JNI_OK);
3248 return JNI_OK;
3249 JNI_END
3250
3251
3252 JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3253 return Modules::get_module(clazz, THREAD);
3254 JNI_END
3255
3256 // Structure containing all jni functions
3257 struct JNINativeInterface_ jni_NativeInterface = {
3258 NULL,
3259 NULL,
3260 NULL,
3261
3262 NULL,
3263
3264 jni_GetVersion,
3265
3266 jni_DefineClass,
3267 jni_FindClass,
3268
3269 jni_FromReflectedMethod,
3270 jni_FromReflectedField,
3271
3272 jni_ToReflectedMethod,
3273
3274 jni_GetSuperclass,
3275 jni_IsAssignableFrom,
3519 jni_ReleasePrimitiveArrayCritical,
3520
3521 jni_GetStringCritical,
3522 jni_ReleaseStringCritical,
3523
3524 jni_NewWeakGlobalRef,
3525 jni_DeleteWeakGlobalRef,
3526
3527 jni_ExceptionCheck,
3528
3529 jni_NewDirectByteBuffer,
3530 jni_GetDirectBufferAddress,
3531 jni_GetDirectBufferCapacity,
3532
3533 // New 1_6 features
3534
3535 jni_GetObjectRefType,
3536
3537 // Module features
3538
3539 jni_GetModule,
3540
3541 };
3542
3543
3544 // For jvmti use to modify jni function table.
3545 // Java threads in native contiues to run until it is transitioned
3546 // to VM at safepoint. Before the transition or before it is blocked
3547 // for safepoint it may access jni function table. VM could crash if
3548 // any java thread access the jni function table in the middle of memcpy.
3549 // To avoid this each function pointers are copied automically.
3550 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3551 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3552 intptr_t *a = (intptr_t *) jni_functions();
3553 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3554 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3555 Atomic::store(a++, *b++);
3556 }
3557 }
3558
3559 void quicken_jni_functions() {
3560 // Replace Get<Primitive>Field with fast versions
|