38 #include "classfile/symbolTable.hpp"
39 #include "classfile/systemDictionary.hpp"
40 #include "classfile/vmClasses.hpp"
41 #include "classfile/vmSymbols.hpp"
42 #include "compiler/compiler_globals.hpp"
43 #include "gc/shared/collectedHeap.hpp"
44 #include "gc/shared/gcLocker.inline.hpp"
45 #include "gc/shared/stringdedup/stringDedup.hpp"
46 #include "interpreter/linkResolver.hpp"
47 #include "jni.h"
48 #include "jvm.h"
49 #include "logging/log.hpp"
50 #include "memory/allocation.hpp"
51 #include "memory/allocation.inline.hpp"
52 #include "memory/oopFactory.hpp"
53 #include "memory/resourceArea.hpp"
54 #include "memory/universe.hpp"
55 #include "nmt/memTracker.hpp"
56 #include "oops/access.inline.hpp"
57 #include "oops/arrayOop.hpp"
58 #include "oops/instanceKlass.inline.hpp"
59 #include "oops/instanceOop.hpp"
60 #include "oops/klass.inline.hpp"
61 #include "oops/markWord.hpp"
62 #include "oops/method.hpp"
63 #include "oops/objArrayKlass.hpp"
64 #include "oops/objArrayOop.inline.hpp"
65 #include "oops/oop.inline.hpp"
66 #include "oops/symbol.hpp"
67 #include "oops/typeArrayKlass.hpp"
68 #include "oops/typeArrayOop.inline.hpp"
69 #include "prims/jniCheck.hpp"
70 #include "prims/jniExport.hpp"
71 #include "prims/jniFastGetField.hpp"
72 #include "prims/jvm_misc.hpp"
73 #include "prims/jvmtiExport.hpp"
74 #include "prims/jvmtiThreadState.hpp"
75 #include "runtime/arguments.hpp"
76 #include "runtime/atomic.hpp"
77 #include "runtime/fieldDescriptor.inline.hpp"
409 int modifiers = java_lang_reflect_Field::modifiers(reflected);
410
411 // Make sure class is initialized before handing id's out to fields
412 k1->initialize(CHECK_NULL);
413
414 // First check if this is a static field
415 if (modifiers & JVM_ACC_STATIC) {
416 int offset = InstanceKlass::cast(k1)->field_offset( slot );
417 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
418 assert(id != nullptr, "corrupt Field object");
419 debug_only(id->set_is_static_field_id();)
420 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
421 ret = jfieldIDWorkaround::to_static_jfieldID(id);
422 return ret;
423 }
424
425 // The slot is the index of the field description in the field-array
426 // The jfieldID is the offset of the field within the object
427 // It may also have hash bits for k, if VerifyJNIFields is turned on.
428 int offset = InstanceKlass::cast(k1)->field_offset( slot );
429 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
430 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
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 = nullptr;
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_initializer()) {
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 = nullptr;
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 nullptr;
785 }
786
787 friend class SignatureIterator; // so do_parameters_on can call do_type
788 void do_type(BasicType type) {
789 switch (type) {
790 // these are coerced to int when using va_arg
791 case T_BYTE:
792 case T_CHAR:
793 case T_SHORT:
794 case T_INT: push_int(va_arg(_ap, jint)); break;
795 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
796
797 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
798
799 case T_LONG: push_long(va_arg(_ap, jlong)); break;
800 // float is coerced to double w/ va_arg
801 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
802 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
803
804 case T_ARRAY:
805 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
806 default: ShouldNotReachHere();
807 }
808 }
809
810 public:
811 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
812 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
813 set_ap(rap);
814 }
815
816 ~JNI_ArgumentPusherVaArg() {
817 va_end(_ap);
818 }
819
820 virtual void push_arguments_on(JavaCallArguments* arguments) {
821 _arguments = arguments;
822 do_parameters_on(this);
823 }
824 };
825
826
827 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
828 protected:
829 const jvalue *_ap;
830
831 inline void set_ap(const jvalue *rap) { _ap = rap; }
832
833 friend class SignatureIterator; // so do_parameters_on can call do_type
834 void do_type(BasicType type) {
835 switch (type) {
836 case T_CHAR: push_int((_ap++)->c); break;
837 case T_SHORT: push_int((_ap++)->s); break;
838 case T_BYTE: push_int((_ap++)->b); break;
839 case T_INT: push_int((_ap++)->i); break;
840 case T_BOOLEAN: push_boolean((_ap++)->z); break;
841 case T_LONG: push_long((_ap++)->j); break;
842 case T_FLOAT: push_float((_ap++)->f); break;
843 case T_DOUBLE: push_double((_ap++)->d); break;
844 case T_ARRAY:
845 case T_OBJECT: push_object((_ap++)->l); break;
846 default: ShouldNotReachHere();
847 }
848 }
849
850 public:
851 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
852 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
853 set_ap(rap);
854 }
855
856 virtual void push_arguments_on(JavaCallArguments* arguments) {
857 _arguments = arguments;
858 do_parameters_on(this);
859 }
860 };
861
862
863 enum JNICallType {
864 JNI_STATIC,
865 JNI_VIRTUAL,
952 result->set_type(args->return_type());
953
954 // Invoke the method. Result is returned as oop.
955 JavaCalls::call(result, method, &java_args, CHECK);
956
957 // Convert result
958 if (is_reference_type(result->get_type())) {
959 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
960 }
961 }
962
963 DT_RETURN_MARK_DECL(AllocObject, jobject
964 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
965
966 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
967 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
968
969 jobject ret = nullptr;
970 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
971
972 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
973 ret = JNIHandles::make_local(THREAD, i);
974 return ret;
975 JNI_END
976
977 DT_RETURN_MARK_DECL(NewObjectA, jobject
978 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
979
980 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
981 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
982
983 jobject obj = nullptr;
984 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
985
986 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
987 obj = JNIHandles::make_local(THREAD, i);
988 JavaValue jvalue(T_VOID);
989 JNI_ArgumentPusherArray ap(methodID, args);
990 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
991 return obj;
992 JNI_END
993
994
995 DT_RETURN_MARK_DECL(NewObjectV, jobject
996 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
997
998 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
999 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1000
1001 jobject obj = nullptr;
1002 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1003
1004 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1005 obj = JNIHandles::make_local(THREAD, i);
1006 JavaValue jvalue(T_VOID);
1007 JNI_ArgumentPusherVaArg ap(methodID, args);
1008 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1009 return obj;
1010 JNI_END
1011
1012
1013 DT_RETURN_MARK_DECL(NewObject, jobject
1014 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1015
1016 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1017 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1018
1019 jobject obj = nullptr;
1020 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1021
1022 instanceOop i = InstanceKlass::allocate_instance(JNIHandles::resolve_non_null(clazz), CHECK_NULL);
1023 obj = JNIHandles::make_local(THREAD, i);
1024 va_list args;
1025 va_start(args, methodID);
1026 JavaValue jvalue(T_VOID);
1027 JNI_ArgumentPusherVaArg ap(methodID, args);
1028 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1029 va_end(args);
1030 return obj;
1031 JNI_END
1032
1033
1034 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1035 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1036
1037 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1038 jclass ret =
1039 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1040
1041 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1042 return ret;
1043 JNI_END
1044
1045 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1046 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1047
1048 jboolean ret = JNI_TRUE;
1049 if (obj != nullptr) {
1760 // table. If they're not there, the field doesn't exist.
1761 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1762 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1763 if (fieldname == nullptr || signame == nullptr) {
1764 ResourceMark rm;
1765 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1766 }
1767
1768 // Make sure class is initialized before handing id's out to fields
1769 k->initialize(CHECK_NULL);
1770
1771 fieldDescriptor fd;
1772 if (!k->is_instance_klass() ||
1773 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1774 ResourceMark rm;
1775 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1776 }
1777
1778 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1779 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1780 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
1781 return ret;
1782 JNI_END
1783
1784
1785 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1786 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1787 oop o = JNIHandles::resolve_non_null(obj);
1788 Klass* k = o->klass();
1789 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1790 // Keep JVMTI addition small and only check enabled flag here.
1791 // jni_GetField_probe() assumes that is okay to create handles.
1792 if (JvmtiExport::should_post_field_access()) {
1793 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1794 }
1795 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1796 jobject ret = JNIHandles::make_local(THREAD, loaded_obj);
1797 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1798 return ret;
1799 JNI_END
1800
1801
1802
1803 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1804 , EntryProbe, ReturnProbe) \
1805 \
1806 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1807 , ReturnProbe); \
1808 \
1809 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1810 \
1811 EntryProbe; \
1812 Return ret = 0;\
1813 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1814 \
1815 oop o = JNIHandles::resolve_non_null(obj); \
1816 Klass* k = o->klass(); \
1868 return (address)jni_GetLongField;
1869 }
1870 address jni_GetFloatField_addr() {
1871 return (address)jni_GetFloatField;
1872 }
1873 address jni_GetDoubleField_addr() {
1874 return (address)jni_GetDoubleField;
1875 }
1876
1877 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1878 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1879 oop o = JNIHandles::resolve_non_null(obj);
1880 Klass* k = o->klass();
1881 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1882 // Keep JVMTI addition small and only check enabled flag here.
1883 if (JvmtiExport::should_post_field_modification()) {
1884 jvalue field_value;
1885 field_value.l = value;
1886 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1887 }
1888 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1889 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1890 JNI_END
1891
1892 // TODO: make this a template
1893
1894 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1895 , EntryProbe, ReturnProbe) \
1896 \
1897 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1898 \
1899 EntryProbe; \
1900 \
1901 oop o = JNIHandles::resolve_non_null(obj); \
1902 Klass* k = o->klass(); \
1903 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1904 /* Keep JVMTI addition small and only check enabled flag here. */ \
1905 if (JvmtiExport::should_post_field_modification()) { \
1906 jvalue field_value; \
1907 field_value.unionType = value; \
1908 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
2293 Klass* ak = ek->array_klass(CHECK_NULL);
2294 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2295 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2296 oop initial_value = JNIHandles::resolve(initialElement);
2297 if (initial_value != nullptr) { // array already initialized with null
2298 for (int index = 0; index < length; index++) {
2299 result->obj_at_put(index, initial_value);
2300 }
2301 }
2302 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2303 return ret;
2304 JNI_END
2305
2306 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2307 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2308
2309 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2310 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2311 jobject ret = nullptr;
2312 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2313 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2314 if (a->is_within_bounds(index)) {
2315 ret = JNIHandles::make_local(THREAD, a->obj_at(index));
2316 return ret;
2317 } else {
2318 ResourceMark rm(THREAD);
2319 stringStream ss;
2320 ss.print("Index %d out of bounds for length %d", index, a->length());
2321 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2322 }
2323 JNI_END
2324
2325 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2326 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2327
2328 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2329 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2330 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2331
2332 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2333 oop v = JNIHandles::resolve(value);
2334 if (a->is_within_bounds(index)) {
2335 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2336 a->obj_at_put(index, v);
2337 } else {
2338 ResourceMark rm(THREAD);
2339 stringStream ss;
2340 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2341 ss.print("type mismatch: can not store %s to %s[%d]",
2342 v->klass()->external_name(),
2343 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2344 index);
2345 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2346 ss.print("[]");
2347 }
2348 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2349 }
2350 } else {
2351 ResourceMark rm(THREAD);
2352 stringStream ss;
2353 ss.print("Index %d out of bounds for length %d", index, a->length());
2354 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2355 }
2356 JNI_END
2357
2358
2359
2360 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2361 ,EntryProbe,ReturnProbe) \
2362 \
2363 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2364 , ReturnProbe); \
2365 \
2366 JNI_ENTRY(Return, \
2367 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2368 EntryProbe; \
2369 Return ret = nullptr;\
2370 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2371 \
2372 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2373 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2374 return ret;\
2375 JNI_END
|
38 #include "classfile/symbolTable.hpp"
39 #include "classfile/systemDictionary.hpp"
40 #include "classfile/vmClasses.hpp"
41 #include "classfile/vmSymbols.hpp"
42 #include "compiler/compiler_globals.hpp"
43 #include "gc/shared/collectedHeap.hpp"
44 #include "gc/shared/gcLocker.inline.hpp"
45 #include "gc/shared/stringdedup/stringDedup.hpp"
46 #include "interpreter/linkResolver.hpp"
47 #include "jni.h"
48 #include "jvm.h"
49 #include "logging/log.hpp"
50 #include "memory/allocation.hpp"
51 #include "memory/allocation.inline.hpp"
52 #include "memory/oopFactory.hpp"
53 #include "memory/resourceArea.hpp"
54 #include "memory/universe.hpp"
55 #include "nmt/memTracker.hpp"
56 #include "oops/access.inline.hpp"
57 #include "oops/arrayOop.hpp"
58 #include "oops/flatArrayOop.inline.hpp"
59 #include "oops/inlineKlass.inline.hpp"
60 #include "oops/instanceKlass.inline.hpp"
61 #include "oops/instanceOop.hpp"
62 #include "oops/klass.inline.hpp"
63 #include "oops/markWord.hpp"
64 #include "oops/method.hpp"
65 #include "oops/objArrayKlass.hpp"
66 #include "oops/objArrayOop.inline.hpp"
67 #include "oops/oop.inline.hpp"
68 #include "oops/symbol.hpp"
69 #include "oops/typeArrayKlass.hpp"
70 #include "oops/typeArrayOop.inline.hpp"
71 #include "prims/jniCheck.hpp"
72 #include "prims/jniExport.hpp"
73 #include "prims/jniFastGetField.hpp"
74 #include "prims/jvm_misc.hpp"
75 #include "prims/jvmtiExport.hpp"
76 #include "prims/jvmtiThreadState.hpp"
77 #include "runtime/arguments.hpp"
78 #include "runtime/atomic.hpp"
79 #include "runtime/fieldDescriptor.inline.hpp"
411 int modifiers = java_lang_reflect_Field::modifiers(reflected);
412
413 // Make sure class is initialized before handing id's out to fields
414 k1->initialize(CHECK_NULL);
415
416 // First check if this is a static field
417 if (modifiers & JVM_ACC_STATIC) {
418 int offset = InstanceKlass::cast(k1)->field_offset( slot );
419 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
420 assert(id != nullptr, "corrupt Field object");
421 debug_only(id->set_is_static_field_id();)
422 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
423 ret = jfieldIDWorkaround::to_static_jfieldID(id);
424 return ret;
425 }
426
427 // The slot is the index of the field description in the field-array
428 // The jfieldID is the offset of the field within the object
429 // It may also have hash bits for k, if VerifyJNIFields is turned on.
430 int offset = InstanceKlass::cast(k1)->field_offset( slot );
431 bool is_flat = InstanceKlass::cast(k1)->field_is_flat(slot);
432 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
433 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset, is_flat);
434 return ret;
435 JNI_END
436
437
438 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
439 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
440
441 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
442 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
443
444 jobject ret = nullptr;
445 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
446
447 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
448 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
449 oop reflection_method;
450 if (m->is_object_constructor()) {
451 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
452 } else {
453 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
454 }
455 ret = JNIHandles::make_local(THREAD, reflection_method);
456 return ret;
457 JNI_END
458
459 DT_RETURN_MARK_DECL(GetSuperclass, jclass
460 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
461
462 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
463 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
464
465 jclass obj = nullptr;
466 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
467
468 oop mirror = JNIHandles::resolve_non_null(sub);
469 // primitive classes return null
470 if (java_lang_Class::is_primitive(mirror)) return nullptr;
788 }
789
790 friend class SignatureIterator; // so do_parameters_on can call do_type
791 void do_type(BasicType type) {
792 switch (type) {
793 // these are coerced to int when using va_arg
794 case T_BYTE:
795 case T_CHAR:
796 case T_SHORT:
797 case T_INT: push_int(va_arg(_ap, jint)); break;
798 case T_BOOLEAN: push_boolean((jboolean) va_arg(_ap, jint)); break;
799
800 // each of these paths is exercised by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
801
802 case T_LONG: push_long(va_arg(_ap, jlong)); break;
803 // float is coerced to double w/ va_arg
804 case T_FLOAT: push_float((jfloat) va_arg(_ap, jdouble)); break;
805 case T_DOUBLE: push_double(va_arg(_ap, jdouble)); break;
806
807 case T_ARRAY:
808 case T_OBJECT: push_object(va_arg(_ap, jobject)); break;
809 default: ShouldNotReachHere();
810 }
811 }
812
813 public:
814 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
815 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
816 set_ap(rap);
817 }
818
819 ~JNI_ArgumentPusherVaArg() {
820 va_end(_ap);
821 }
822
823 virtual void push_arguments_on(JavaCallArguments* arguments) {
824 _arguments = arguments;
825 do_parameters_on(this);
826 }
827 };
828
829
830 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
831 protected:
832 const jvalue *_ap;
833
834 inline void set_ap(const jvalue *rap) { _ap = rap; }
835
836 friend class SignatureIterator; // so do_parameters_on can call do_type
837 void do_type(BasicType type) {
838 switch (type) {
839 case T_CHAR: push_int((_ap++)->c); break;
840 case T_SHORT: push_int((_ap++)->s); break;
841 case T_BYTE: push_int((_ap++)->b); break;
842 case T_INT: push_int((_ap++)->i); break;
843 case T_BOOLEAN: push_boolean((_ap++)->z); break;
844 case T_LONG: push_long((_ap++)->j); break;
845 case T_FLOAT: push_float((_ap++)->f); break;
846 case T_DOUBLE: push_double((_ap++)->d); break;
847 case T_ARRAY:
848 case T_OBJECT:
849 case T_PRIMITIVE_OBJECT: push_object((_ap++)->l); break;
850 default: ShouldNotReachHere();
851 }
852 }
853
854 public:
855 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
856 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)) {
857 set_ap(rap);
858 }
859
860 virtual void push_arguments_on(JavaCallArguments* arguments) {
861 _arguments = arguments;
862 do_parameters_on(this);
863 }
864 };
865
866
867 enum JNICallType {
868 JNI_STATIC,
869 JNI_VIRTUAL,
956 result->set_type(args->return_type());
957
958 // Invoke the method. Result is returned as oop.
959 JavaCalls::call(result, method, &java_args, CHECK);
960
961 // Convert result
962 if (is_reference_type(result->get_type())) {
963 result->set_jobject(JNIHandles::make_local(THREAD, result->get_oop()));
964 }
965 }
966
967 DT_RETURN_MARK_DECL(AllocObject, jobject
968 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
969
970 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
971 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
972
973 jobject ret = nullptr;
974 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
975
976 oop clazzoop = JNIHandles::resolve_non_null(clazz);
977 Klass* k = java_lang_Class::as_Klass(clazzoop);
978 if (k == nullptr || k->is_inline_klass()) {
979 ResourceMark rm(THREAD);
980 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
981 }
982 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
983 ret = JNIHandles::make_local(THREAD, i);
984 return ret;
985 JNI_END
986
987 DT_RETURN_MARK_DECL(NewObjectA, jobject
988 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
989
990 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
991 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
992
993 jobject obj = nullptr;
994 DT_RETURN_MARK(NewObjectA, jobject, (const jobject&)obj);
995
996 oop clazzoop = JNIHandles::resolve_non_null(clazz);
997 Klass* k = java_lang_Class::as_Klass(clazzoop);
998 if (k == nullptr) {
999 ResourceMark rm(THREAD);
1000 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1001 }
1002
1003 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1004 obj = JNIHandles::make_local(THREAD, i);
1005 JavaValue jvalue(T_VOID);
1006 JNI_ArgumentPusherArray ap(methodID, args);
1007 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1008
1009 return obj;
1010 JNI_END
1011
1012
1013 DT_RETURN_MARK_DECL(NewObjectV, jobject
1014 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1015
1016 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1017 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1018
1019 jobject obj = nullptr;
1020 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1021
1022 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1023 Klass* k = java_lang_Class::as_Klass(clazzoop);
1024 if (k == nullptr) {
1025 ResourceMark rm(THREAD);
1026 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1027 }
1028
1029 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1030 obj = JNIHandles::make_local(THREAD, i);
1031 JavaValue jvalue(T_VOID);
1032 JNI_ArgumentPusherVaArg ap(methodID, args);
1033 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1034
1035 return obj;
1036 JNI_END
1037
1038
1039 DT_RETURN_MARK_DECL(NewObject, jobject
1040 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1041
1042 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1043 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1044
1045 jobject obj = nullptr;
1046 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1047
1048 oop clazzoop = JNIHandles::resolve_non_null(clazz);
1049 Klass* k = java_lang_Class::as_Klass(clazzoop);
1050 if (k == nullptr) {
1051 ResourceMark rm(THREAD);
1052 THROW_(vmSymbols::java_lang_InstantiationException(), nullptr);
1053 }
1054
1055 instanceOop i = InstanceKlass::allocate_instance(clazzoop, CHECK_NULL);
1056 obj = JNIHandles::make_local(THREAD, i);
1057 va_list args;
1058 va_start(args, methodID);
1059 JavaValue jvalue(T_VOID);
1060 JNI_ArgumentPusherVaArg ap(methodID, args);
1061 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1062 va_end(args);
1063
1064 return obj;
1065 JNI_END
1066
1067
1068 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1069 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1070
1071 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1072 jclass ret =
1073 (jclass) JNIHandles::make_local(THREAD, k->java_mirror());
1074
1075 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1076 return ret;
1077 JNI_END
1078
1079 JNI_ENTRY_NO_PRESERVE(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1080 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1081
1082 jboolean ret = JNI_TRUE;
1083 if (obj != nullptr) {
1794 // table. If they're not there, the field doesn't exist.
1795 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
1796 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
1797 if (fieldname == nullptr || signame == nullptr) {
1798 ResourceMark rm;
1799 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1800 }
1801
1802 // Make sure class is initialized before handing id's out to fields
1803 k->initialize(CHECK_NULL);
1804
1805 fieldDescriptor fd;
1806 if (!k->is_instance_klass() ||
1807 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
1808 ResourceMark rm;
1809 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
1810 }
1811
1812 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
1813 // It may also have hash bits for k, if VerifyJNIFields is turned on.
1814 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset(), fd.is_flat());
1815 return ret;
1816 JNI_END
1817
1818
1819 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
1820 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
1821 oop o = JNIHandles::resolve_non_null(obj);
1822 Klass* k = o->klass();
1823 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1824 oop res = nullptr;
1825 // Keep JVMTI addition small and only check enabled flag here.
1826 // jni_GetField_probe() assumes that is okay to create handles.
1827 if (JvmtiExport::should_post_field_access()) {
1828 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
1829 }
1830 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1831 res = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
1832 } else {
1833 assert(k->is_instance_klass(), "Only instance can have flat fields");
1834 InstanceKlass* ik = InstanceKlass::cast(k);
1835 fieldDescriptor fd;
1836 ik->find_field_from_offset(offset, false, &fd); // performance bottleneck
1837 InstanceKlass* holder = fd.field_holder();
1838 InlineKlass* field_vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1839 res = field_vklass->read_flat_field(o, ik->field_offset(fd.index()), CHECK_NULL);
1840 }
1841 jobject ret = JNIHandles::make_local(THREAD, res);
1842 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
1843 return ret;
1844 JNI_END
1845
1846
1847
1848 #define DEFINE_GETFIELD(Return,Fieldname,Result \
1849 , EntryProbe, ReturnProbe) \
1850 \
1851 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
1852 , ReturnProbe); \
1853 \
1854 JNI_ENTRY_NO_PRESERVE(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
1855 \
1856 EntryProbe; \
1857 Return ret = 0;\
1858 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
1859 \
1860 oop o = JNIHandles::resolve_non_null(obj); \
1861 Klass* k = o->klass(); \
1913 return (address)jni_GetLongField;
1914 }
1915 address jni_GetFloatField_addr() {
1916 return (address)jni_GetFloatField;
1917 }
1918 address jni_GetDoubleField_addr() {
1919 return (address)jni_GetDoubleField;
1920 }
1921
1922 JNI_ENTRY_NO_PRESERVE(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
1923 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
1924 oop o = JNIHandles::resolve_non_null(obj);
1925 Klass* k = o->klass();
1926 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
1927 // Keep JVMTI addition small and only check enabled flag here.
1928 if (JvmtiExport::should_post_field_modification()) {
1929 jvalue field_value;
1930 field_value.l = value;
1931 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, JVM_SIGNATURE_CLASS, (jvalue *)&field_value);
1932 }
1933 if (!jfieldIDWorkaround::is_flat_jfieldID(fieldID)) {
1934 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
1935 } else {
1936 assert(k->is_instance_klass(), "Only instances can have flat fields");
1937 InstanceKlass* ik = InstanceKlass::cast(k);
1938 fieldDescriptor fd;
1939 ik->find_field_from_offset(offset, false, &fd);
1940 InstanceKlass* holder = fd.field_holder();
1941 InlineKlass* vklass = InlineKlass::cast(holder->get_inline_type_field_klass(fd.index()));
1942 oop v = JNIHandles::resolve_non_null(value);
1943 vklass->write_flat_field(o, offset, v, CHECK);
1944 }
1945 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
1946 JNI_END
1947
1948 // TODO: make this a template
1949
1950 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
1951 , EntryProbe, ReturnProbe) \
1952 \
1953 JNI_ENTRY_NO_PRESERVE(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
1954 \
1955 EntryProbe; \
1956 \
1957 oop o = JNIHandles::resolve_non_null(obj); \
1958 Klass* k = o->klass(); \
1959 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
1960 /* Keep JVMTI addition small and only check enabled flag here. */ \
1961 if (JvmtiExport::should_post_field_modification()) { \
1962 jvalue field_value; \
1963 field_value.unionType = value; \
1964 o = JvmtiExport::jni_SetField_probe(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
2349 Klass* ak = ek->array_klass(CHECK_NULL);
2350 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2351 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2352 oop initial_value = JNIHandles::resolve(initialElement);
2353 if (initial_value != nullptr) { // array already initialized with null
2354 for (int index = 0; index < length; index++) {
2355 result->obj_at_put(index, initial_value);
2356 }
2357 }
2358 ret = (jobjectArray) JNIHandles::make_local(THREAD, result);
2359 return ret;
2360 JNI_END
2361
2362 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2363 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2364
2365 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2366 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2367 jobject ret = nullptr;
2368 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2369 oop res = nullptr;
2370 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2371 if (arr->is_within_bounds(index)) {
2372 if (arr->is_flatArray()) {
2373 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2374 flatArrayHandle vah(thread, a);
2375 res = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK_NULL);
2376 assert(res != nullptr, "Must be set in one of two paths above");
2377 } else {
2378 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2379 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2380 res = a->obj_at(index);
2381 }
2382 } else {
2383 ResourceMark rm(THREAD);
2384 stringStream ss;
2385 ss.print("Index %d out of bounds for length %d", index,arr->length());
2386 THROW_MSG_NULL(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2387 }
2388 ret = JNIHandles::make_local(THREAD, res);
2389 return ret;
2390 JNI_END
2391
2392 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2393 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2394
2395 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2396 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2397 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2398
2399 bool oob = false;
2400 int length = -1;
2401 oop res = nullptr;
2402 arrayOop arr((arrayOop)JNIHandles::resolve_non_null(array));
2403 if (arr->is_within_bounds(index)) {
2404 if (arr->is_flatArray()) {
2405 flatArrayOop a = flatArrayOop(JNIHandles::resolve_non_null(array));
2406 oop v = JNIHandles::resolve(value);
2407 FlatArrayKlass* vaklass = FlatArrayKlass::cast(a->klass());
2408 InlineKlass* element_vklass = vaklass->element_klass();
2409 if (v != nullptr && v->is_a(element_vklass)) {
2410 a->value_copy_to_index(v, index);
2411 } else {
2412 ResourceMark rm(THREAD);
2413 stringStream ss;
2414 Klass *kl = FlatArrayKlass::cast(a->klass());
2415 ss.print("type mismatch: can not store %s to %s[%d]",
2416 v->klass()->external_name(),
2417 kl->external_name(),
2418 index);
2419 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2420 ss.print("[]");
2421 }
2422 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2423 }
2424 } else {
2425 assert(arr->is_objArray(), "If not a valueArray. must be an objArray");
2426 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2427 oop v = JNIHandles::resolve(value);
2428 if (v == nullptr || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2429 a->obj_at_put(index, v);
2430 } else {
2431 ResourceMark rm(THREAD);
2432 stringStream ss;
2433 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2434 ss.print("type mismatch: can not store %s to %s[%d]",
2435 v->klass()->external_name(),
2436 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2437 index);
2438 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2439 ss.print("[]");
2440 }
2441 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2442 }
2443 }
2444 } else {
2445 ResourceMark rm(THREAD);
2446 stringStream ss;
2447 ss.print("Index %d out of bounds for length %d", index, arr->length());
2448 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2449 }
2450 JNI_END
2451
2452
2453
2454 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2455 ,EntryProbe,ReturnProbe) \
2456 \
2457 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2458 , ReturnProbe); \
2459 \
2460 JNI_ENTRY(Return, \
2461 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2462 EntryProbe; \
2463 Return ret = nullptr;\
2464 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2465 \
2466 oop obj= oopFactory::Allocator(len, CHECK_NULL); \
2467 ret = (Return) JNIHandles::make_local(THREAD, obj); \
2468 return ret;\
2469 JNI_END
|