1/*
2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
3 * Copyright (c) 2012 Red Hat, Inc.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26#include "precompiled.hpp"
27#include "jni.h"
28#include "jvm.h"
29#include "ci/ciReplay.hpp"
30#include "classfile/altHashing.hpp"
31#include "classfile/classFileStream.hpp"
32#include "classfile/classLoader.hpp"
33#include "classfile/javaClasses.hpp"
34#include "classfile/javaClasses.inline.hpp"
35#include "classfile/modules.hpp"
36#include "classfile/symbolTable.hpp"
37#include "classfile/systemDictionary.hpp"
38#include "classfile/vmSymbols.hpp"
39#include "gc/shared/gcLocker.inline.hpp"
40#include "interpreter/linkResolver.hpp"
41#include "jfr/jfrEvents.hpp"
42#include "jfr/support/jfrThreadId.hpp"
43#include "logging/log.hpp"
44#include "memory/allocation.hpp"
45#include "memory/allocation.inline.hpp"
46#include "memory/oopFactory.hpp"
47#include "memory/resourceArea.hpp"
48#include "memory/universe.hpp"
49#include "oops/access.inline.hpp"
50#include "oops/arrayOop.inline.hpp"
51#include "oops/instanceKlass.hpp"
52#include "oops/instanceOop.hpp"
53#include "oops/markOop.hpp"
54#include "oops/method.hpp"
55#include "oops/objArrayKlass.hpp"
56#include "oops/objArrayOop.inline.hpp"
57#include "oops/oop.inline.hpp"
58#include "oops/symbol.hpp"
59#include "oops/typeArrayKlass.hpp"
60#include "oops/typeArrayOop.inline.hpp"
61#include "prims/jniCheck.hpp"
62#include "prims/jniExport.hpp"
63#include "prims/jniFastGetField.hpp"
64#include "prims/jvm_misc.hpp"
65#include "prims/jvmtiExport.hpp"
66#include "prims/jvmtiThreadState.hpp"
67#include "runtime/atomic.hpp"
68#include "runtime/compilationPolicy.hpp"
69#include "runtime/fieldDescriptor.inline.hpp"
70#include "runtime/handles.inline.hpp"
71#include "runtime/interfaceSupport.inline.hpp"
72#include "runtime/java.hpp"
73#include "runtime/javaCalls.hpp"
74#include "runtime/jfieldIDWorkaround.hpp"
75#include "runtime/jniHandles.inline.hpp"
76#include "runtime/orderAccess.hpp"
77#include "runtime/reflection.hpp"
78#include "runtime/safepointVerifiers.hpp"
79#include "runtime/sharedRuntime.hpp"
80#include "runtime/signature.hpp"
81#include "runtime/thread.inline.hpp"
82#include "runtime/vmOperations.hpp"
83#include "services/memTracker.hpp"
84#include "services/runtimeService.hpp"
85#include "utilities/defaultStream.hpp"
86#include "utilities/dtrace.hpp"
87#include "utilities/events.hpp"
88#include "utilities/histogram.hpp"
89#include "utilities/macros.hpp"
90#include "utilities/vmError.hpp"
91
92static jint CurrentVersion = JNI_VERSION_10;
93
94#ifdef _WIN32
95extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* );
96#endif
97
98// The DT_RETURN_MARK macros create a scoped object to fire the dtrace
99// '-return' probe regardless of the return path is taken out of the function.
100// Methods that have multiple return paths use this to avoid having to
101// instrument each return path. Methods that use CHECK or THROW must use this
102// since those macros can cause an immedate uninstrumented return.
103//
104// In order to get the return value, a reference to the variable containing
105// the return value must be passed to the contructor of the object, and
106// the return value must be set before return (since the mark object has
107// a reference to it).
108//
109// Example:
110// DT_RETURN_MARK_DECL(SomeFunc, int);
111// JNI_ENTRY(int, SomeFunc, ...)
112// int return_value = 0;
113// DT_RETURN_MARK(SomeFunc, int, (const int&)return_value);
114// foo(CHECK_0)
115// return_value = 5;
116// return return_value;
117// JNI_END
118#define DT_RETURN_MARK_DECL(name, type, probe) \
119 DTRACE_ONLY( \
120 class DTraceReturnProbeMark_##name { \
121 public: \
122 const type& _ret_ref; \
123 DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \
124 ~DTraceReturnProbeMark_##name() { \
125 probe; \
126 } \
127 } \
128 )
129// Void functions are simpler since there's no return value
130#define DT_VOID_RETURN_MARK_DECL(name, probe) \
131 DTRACE_ONLY( \
132 class DTraceReturnProbeMark_##name { \
133 public: \
134 ~DTraceReturnProbeMark_##name() { \
135 probe; \
136 } \
137 } \
138 )
139
140// Place these macros in the function to mark the return. Non-void
141// functions need the type and address of the return value.
142#define DT_RETURN_MARK(name, type, ref) \
143 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) )
144#define DT_VOID_RETURN_MARK(name) \
145 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark )
146
147
148// Use these to select distinct code for floating-point vs. non-floating point
149// situations. Used from within common macros where we need slightly
150// different behavior for Float/Double
151#define FP_SELECT_Boolean(intcode, fpcode) intcode
152#define FP_SELECT_Byte(intcode, fpcode) intcode
153#define FP_SELECT_Char(intcode, fpcode) intcode
154#define FP_SELECT_Short(intcode, fpcode) intcode
155#define FP_SELECT_Object(intcode, fpcode) intcode
156#define FP_SELECT_Int(intcode, fpcode) intcode
157#define FP_SELECT_Long(intcode, fpcode) intcode
158#define FP_SELECT_Float(intcode, fpcode) fpcode
159#define FP_SELECT_Double(intcode, fpcode) fpcode
160#define FP_SELECT(TypeName, intcode, fpcode) \
161 FP_SELECT_##TypeName(intcode, fpcode)
162
163// Choose DT_RETURN_MARK macros based on the type: float/double -> void
164// (dtrace doesn't do FP yet)
165#define DT_RETURN_MARK_DECL_FOR(TypeName, name, type, probe) \
166 FP_SELECT(TypeName, \
167 DT_RETURN_MARK_DECL(name, type, probe), DT_VOID_RETURN_MARK_DECL(name, probe) )
168#define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \
169 FP_SELECT(TypeName, \
170 DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) )
171
172
173// out-of-line helpers for class jfieldIDWorkaround:
174
175bool jfieldIDWorkaround::is_valid_jfieldID(Klass* k, jfieldID id) {
176 if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) {
177 uintptr_t as_uint = (uintptr_t) id;
178 intptr_t offset = raw_instance_offset(id);
179 if (is_checked_jfieldID(id)) {
180 if (!klass_hash_ok(k, id)) {
181 return false;
182 }
183 }
184 return InstanceKlass::cast(k)->contains_field_offset(offset);
185 } else {
186 JNIid* result = (JNIid*) id;
187#ifdef ASSERT
188 return result != NULL && result->is_static_field_id();
189#else
190 return result != NULL;
191#endif
192 }
193}
194
195
196intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, intptr_t offset) {
197 if (offset <= small_offset_mask) {
198 Klass* field_klass = k;
199 Klass* super_klass = field_klass->super();
200 // With compressed oops the most super class with nonstatic fields would
201 // be the owner of fields embedded in the header.
202 while (InstanceKlass::cast(super_klass)->has_nonstatic_fields() &&
203 InstanceKlass::cast(super_klass)->contains_field_offset(offset)) {
204 field_klass = super_klass; // super contains the field also
205 super_klass = field_klass->super();
206 }
207 debug_only(NoSafepointVerifier nosafepoint;)
208 uintptr_t klass_hash = field_klass->identity_hash();
209 return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
210 } else {
211#if 0
212 #ifndef PRODUCT
213 {
214 ResourceMark rm;
215 warning("VerifyJNIFields: long offset %d in %s", offset, k->external_name());
216 }
217 #endif
218#endif
219 return 0;
220 }
221}
222
223bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
224 uintptr_t as_uint = (uintptr_t) id;
225 intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
226 do {
227 debug_only(NoSafepointVerifier nosafepoint;)
228 // Could use a non-blocking query for identity_hash here...
229 if ((k->identity_hash() & klass_mask) == klass_hash)
230 return true;
231 k = k->super();
232 } while (k != NULL);
233 return false;
234}
235
236void jfieldIDWorkaround::verify_instance_jfieldID(Klass* k, jfieldID id) {
237 guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field" );
238 uintptr_t as_uint = (uintptr_t) id;
239 intptr_t offset = raw_instance_offset(id);
240 if (VerifyJNIFields) {
241 if (is_checked_jfieldID(id)) {
242 guarantee(klass_hash_ok(k, id),
243 "Bug in native code: jfieldID class must match object");
244 } else {
245#if 0
246 #ifndef PRODUCT
247 if (Verbose) {
248 ResourceMark rm;
249 warning("VerifyJNIFields: unverified offset %d for %s", offset, k->external_name());
250 }
251 #endif
252#endif
253 }
254 }
255 guarantee(InstanceKlass::cast(k)->contains_field_offset(offset),
256 "Bug in native code: jfieldID offset must address interior of object");
257}
258
259// Wrapper to trace JNI functions
260
261#ifdef ASSERT
262 Histogram* JNIHistogram;
263 static volatile int JNIHistogram_lock = 0;
264
265 class JNIHistogramElement : public HistogramElement {
266 public:
267 JNIHistogramElement(const char* name);
268 };
269
270 JNIHistogramElement::JNIHistogramElement(const char* elementName) {
271 _name = elementName;
272 uintx count = 0;
273
274 while (Atomic::cmpxchg(1, &JNIHistogram_lock, 0) != 0) {
275 while (OrderAccess::load_acquire(&JNIHistogram_lock) != 0) {
276 count +=1;
277 if ( (WarnOnStalledSpinLock > 0)
278 && (count % WarnOnStalledSpinLock == 0)) {
279 warning("JNIHistogram_lock seems to be stalled");
280 }
281 }
282 }
283
284
285 if(JNIHistogram == NULL)
286 JNIHistogram = new Histogram("JNI Call Counts",100);
287
288 JNIHistogram->add_element(this);
289 Atomic::dec(&JNIHistogram_lock);
290 }
291
292 #define JNICountWrapper(arg) \
293 static JNIHistogramElement* e = new JNIHistogramElement(arg); \
294 /* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \
295 if (e != NULL) e->increment_count()
296 #define JNIWrapper(arg) JNICountWrapper(arg);
297#else
298 #define JNIWrapper(arg)
299#endif
300
301
302// Implementation of JNI entries
303
304DT_RETURN_MARK_DECL(DefineClass, jclass
305 , HOTSPOT_JNI_DEFINECLASS_RETURN(_ret_ref));
306
307JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef,
308 const jbyte *buf, jsize bufLen))
309 JNIWrapper("DefineClass");
310
311 HOTSPOT_JNI_DEFINECLASS_ENTRY(
312 env, (char*) name, loaderRef, (char*) buf, bufLen);
313
314 jclass cls = NULL;
315 DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls);
316
317 TempNewSymbol class_name = NULL;
318 // Since exceptions can be thrown, class initialization can take place
319 // if name is NULL no check for class name in .class stream has to be made.
320 if (name != NULL) {
321 const int str_len = (int)strlen(name);
322 if (str_len > Symbol::max_length()) {
323 // It's impossible to create this class; the name cannot fit
324 // into the constant pool.
325 Exceptions::fthrow(THREAD_AND_LOCATION,
326 vmSymbols::java_lang_NoClassDefFoundError(),
327 "Class name exceeds maximum length of %d: %s",
328 Symbol::max_length(),
329 name);
330 return 0;
331 }
332 class_name = SymbolTable::new_symbol(name);
333 }
334 ResourceMark rm(THREAD);
335 ClassFileStream st((u1*)buf, bufLen, NULL, ClassFileStream::verify);
336 Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));
337
338 if (UsePerfData && !class_loader.is_null()) {
339 // check whether the current caller thread holds the lock or not.
340 // If not, increment the corresponding counter
341 if (ObjectSynchronizer::
342 query_lock_ownership((JavaThread*)THREAD, class_loader) !=
343 ObjectSynchronizer::owner_self) {
344 ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc();
345 }
346 }
347 Klass* k = SystemDictionary::resolve_from_stream(class_name,
348 class_loader,
349 Handle(),
350 &st,
351 CHECK_NULL);
352
353 if (log_is_enabled(Debug, class, resolve) && k != NULL) {
354 trace_class_resolution(k);
355 }
356
357 cls = (jclass)JNIHandles::make_local(
358 env, k->java_mirror());
359 return cls;
360JNI_END
361
362
363
364DT_RETURN_MARK_DECL(FindClass, jclass
365 , HOTSPOT_JNI_FINDCLASS_RETURN(_ret_ref));
366
367JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name))
368 JNIWrapper("FindClass");
369
370 HOTSPOT_JNI_FINDCLASS_ENTRY(env, (char *)name);
371
372 jclass result = NULL;
373 DT_RETURN_MARK(FindClass, jclass, (const jclass&)result);
374
375 // Sanity check the name: it cannot be null or larger than the maximum size
376 // name we can fit in the constant pool.
377 if (name == NULL) {
378 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), "No class name given");
379 }
380 if ((int)strlen(name) > Symbol::max_length()) {
381 Exceptions::fthrow(THREAD_AND_LOCATION,
382 vmSymbols::java_lang_NoClassDefFoundError(),
383 "Class name exceeds maximum length of %d: %s",
384 Symbol::max_length(),
385 name);
386 return 0;
387 }
388
389 //%note jni_3
390 Handle protection_domain;
391 // Find calling class
392 Klass* k = thread->security_get_caller_class(0);
393 // default to the system loader when no context
394 Handle loader(THREAD, SystemDictionary::java_system_loader());
395 if (k != NULL) {
396 // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed
397 // in the correct class context.
398 if (k->class_loader() == NULL &&
399 k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) {
400 JavaValue result(T_OBJECT);
401 JavaCalls::call_static(&result, k,
402 vmSymbols::getFromClass_name(),
403 vmSymbols::void_class_signature(),
404 CHECK_NULL);
405 // When invoked from JNI_OnLoad, NativeLibrary::getFromClass returns
406 // a non-NULL Class object. When invoked from JNI_OnUnload,
407 // it will return NULL to indicate no context.
408 oop mirror = (oop) result.get_jobject();
409 if (mirror != NULL) {
410 Klass* fromClass = java_lang_Class::as_Klass(mirror);
411 loader = Handle(THREAD, fromClass->class_loader());
412 protection_domain = Handle(THREAD, fromClass->protection_domain());
413 }
414 } else {
415 loader = Handle(THREAD, k->class_loader());
416 }
417 }
418
419 TempNewSymbol sym = SymbolTable::new_symbol(name);
420 result = find_class_from_class_loader(env, sym, true, loader,
421 protection_domain, true, thread);
422
423 if (log_is_enabled(Debug, class, resolve) && result != NULL) {
424 trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
425 }
426
427 return result;
428JNI_END
429
430DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID
431 , HOTSPOT_JNI_FROMREFLECTEDMETHOD_RETURN((uintptr_t)_ret_ref));
432
433JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method))
434 JNIWrapper("FromReflectedMethod");
435
436 HOTSPOT_JNI_FROMREFLECTEDMETHOD_ENTRY(env, method);
437
438 jmethodID ret = NULL;
439 DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret);
440
441 // method is a handle to a java.lang.reflect.Method object
442 oop reflected = JNIHandles::resolve_non_null(method);
443 oop mirror = NULL;
444 int slot = 0;
445
446 if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) {
447 mirror = java_lang_reflect_Constructor::clazz(reflected);
448 slot = java_lang_reflect_Constructor::slot(reflected);
449 } else {
450 assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type");
451 mirror = java_lang_reflect_Method::clazz(reflected);
452 slot = java_lang_reflect_Method::slot(reflected);
453 }
454 Klass* k1 = java_lang_Class::as_Klass(mirror);
455
456 // Make sure class is initialized before handing id's out to methods
457 k1->initialize(CHECK_NULL);
458 Method* m = InstanceKlass::cast(k1)->method_with_idnum(slot);
459 ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted
460 return ret;
461JNI_END
462
463DT_RETURN_MARK_DECL(FromReflectedField, jfieldID
464 , HOTSPOT_JNI_FROMREFLECTEDFIELD_RETURN((uintptr_t)_ret_ref));
465
466JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field))
467 JNIWrapper("FromReflectedField");
468
469 HOTSPOT_JNI_FROMREFLECTEDFIELD_ENTRY(env, field);
470
471 jfieldID ret = NULL;
472 DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret);
473
474 // field is a handle to a java.lang.reflect.Field object
475 oop reflected = JNIHandles::resolve_non_null(field);
476 oop mirror = java_lang_reflect_Field::clazz(reflected);
477 Klass* k1 = java_lang_Class::as_Klass(mirror);
478 int slot = java_lang_reflect_Field::slot(reflected);
479 int modifiers = java_lang_reflect_Field::modifiers(reflected);
480
481 // Make sure class is initialized before handing id's out to fields
482 k1->initialize(CHECK_NULL);
483
484 // First check if this is a static field
485 if (modifiers & JVM_ACC_STATIC) {
486 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
487 JNIid* id = InstanceKlass::cast(k1)->jni_id_for(offset);
488 assert(id != NULL, "corrupt Field object");
489 debug_only(id->set_is_static_field_id();)
490 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
491 ret = jfieldIDWorkaround::to_static_jfieldID(id);
492 return ret;
493 }
494
495 // The slot is the index of the field description in the field-array
496 // The jfieldID is the offset of the field within the object
497 // It may also have hash bits for k, if VerifyJNIFields is turned on.
498 intptr_t offset = InstanceKlass::cast(k1)->field_offset( slot );
499 assert(InstanceKlass::cast(k1)->contains_field_offset(offset), "stay within object");
500 ret = jfieldIDWorkaround::to_instance_jfieldID(k1, offset);
501 return ret;
502JNI_END
503
504
505DT_RETURN_MARK_DECL(ToReflectedMethod, jobject
506 , HOTSPOT_JNI_TOREFLECTEDMETHOD_RETURN(_ret_ref));
507
508JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic))
509 JNIWrapper("ToReflectedMethod");
510
511 HOTSPOT_JNI_TOREFLECTEDMETHOD_ENTRY(env, cls, (uintptr_t) method_id, isStatic);
512
513 jobject ret = NULL;
514 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret);
515
516 methodHandle m (THREAD, Method::resolve_jmethod_id(method_id));
517 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match");
518 oop reflection_method;
519 if (m->is_initializer()) {
520 reflection_method = Reflection::new_constructor(m, CHECK_NULL);
521 } else {
522 reflection_method = Reflection::new_method(m, false, CHECK_NULL);
523 }
524 ret = JNIHandles::make_local(env, reflection_method);
525 return ret;
526JNI_END
527
528DT_RETURN_MARK_DECL(GetSuperclass, jclass
529 , HOTSPOT_JNI_GETSUPERCLASS_RETURN(_ret_ref));
530
531JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub))
532 JNIWrapper("GetSuperclass");
533
534 HOTSPOT_JNI_GETSUPERCLASS_ENTRY(env, sub);
535
536 jclass obj = NULL;
537 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj);
538
539 oop mirror = JNIHandles::resolve_non_null(sub);
540 // primitive classes return NULL
541 if (java_lang_Class::is_primitive(mirror)) return NULL;
542
543 // Rules of Class.getSuperClass as implemented by KLass::java_super:
544 // arrays return Object
545 // interfaces return NULL
546 // proper classes return Klass::super()
547 Klass* k = java_lang_Class::as_Klass(mirror);
548 if (k->is_interface()) return NULL;
549
550 // return mirror for superclass
551 Klass* super = k->java_super();
552 // super2 is the value computed by the compiler's getSuperClass intrinsic:
553 debug_only(Klass* super2 = ( k->is_array_klass()
554 ? SystemDictionary::Object_klass()
555 : k->super() ) );
556 assert(super == super2,
557 "java_super computation depends on interface, array, other super");
558 obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(super->java_mirror());
559 return obj;
560JNI_END
561
562JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super))
563 JNIWrapper("IsSubclassOf");
564
565 HOTSPOT_JNI_ISASSIGNABLEFROM_ENTRY(env, sub, super);
566
567 oop sub_mirror = JNIHandles::resolve_non_null(sub);
568 oop super_mirror = JNIHandles::resolve_non_null(super);
569 if (java_lang_Class::is_primitive(sub_mirror) ||
570 java_lang_Class::is_primitive(super_mirror)) {
571 jboolean ret = oopDesc::equals(sub_mirror, super_mirror);
572
573 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
574 return ret;
575 }
576 Klass* sub_klass = java_lang_Class::as_Klass(sub_mirror);
577 Klass* super_klass = java_lang_Class::as_Klass(super_mirror);
578 assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom");
579 jboolean ret = sub_klass->is_subtype_of(super_klass) ?
580 JNI_TRUE : JNI_FALSE;
581
582 HOTSPOT_JNI_ISASSIGNABLEFROM_RETURN(ret);
583 return ret;
584JNI_END
585
586
587DT_RETURN_MARK_DECL(Throw, jint
588 , HOTSPOT_JNI_THROW_RETURN(_ret_ref));
589
590JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj))
591 JNIWrapper("Throw");
592
593 HOTSPOT_JNI_THROW_ENTRY(env, obj);
594
595 jint ret = JNI_OK;
596 DT_RETURN_MARK(Throw, jint, (const jint&)ret);
597
598 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK);
599 ShouldNotReachHere();
600 return 0; // Mute compiler.
601JNI_END
602
603
604DT_RETURN_MARK_DECL(ThrowNew, jint
605 , HOTSPOT_JNI_THROWNEW_RETURN(_ret_ref));
606
607JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message))
608 JNIWrapper("ThrowNew");
609
610 HOTSPOT_JNI_THROWNEW_ENTRY(env, clazz, (char *) message);
611
612 jint ret = JNI_OK;
613 DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret);
614
615 InstanceKlass* k = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
616 Symbol* name = k->name();
617 Handle class_loader (THREAD, k->class_loader());
618 Handle protection_domain (THREAD, k->protection_domain());
619 THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK);
620 ShouldNotReachHere();
621 return 0; // Mute compiler.
622JNI_END
623
624
625// JNI functions only transform a pending async exception to a synchronous
626// exception in ExceptionOccurred and ExceptionCheck calls, since
627// delivering an async exception in other places won't change the native
628// code's control flow and would be harmful when native code further calls
629// JNI functions with a pending exception. Async exception is also checked
630// during the call, so ExceptionOccurred/ExceptionCheck won't return
631// false but deliver the async exception at the very end during
632// state transition.
633
634static void jni_check_async_exceptions(JavaThread *thread) {
635 assert(thread == Thread::current(), "must be itself");
636 thread->check_and_handle_async_exceptions();
637}
638
639JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env))
640 JNIWrapper("ExceptionOccurred");
641
642 HOTSPOT_JNI_EXCEPTIONOCCURRED_ENTRY(env);
643
644 jni_check_async_exceptions(thread);
645 oop exception = thread->pending_exception();
646 jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception);
647
648 HOTSPOT_JNI_EXCEPTIONOCCURRED_RETURN(ret);
649 return ret;
650JNI_END
651
652
653JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env))
654 JNIWrapper("ExceptionDescribe");
655
656 HOTSPOT_JNI_EXCEPTIONDESCRIBE_ENTRY(env);
657
658 if (thread->has_pending_exception()) {
659 Handle ex(thread, thread->pending_exception());
660 thread->clear_pending_exception();
661 if (ex->is_a(SystemDictionary::ThreadDeath_klass())) {
662 // Don't print anything if we are being killed.
663 } else {
664 jio_fprintf(defaultStream::error_stream(), "Exception ");
665 if (thread != NULL && thread->threadObj() != NULL) {
666 ResourceMark rm(THREAD);
667 jio_fprintf(defaultStream::error_stream(),
668 "in thread \"%s\" ", thread->get_thread_name());
669 }
670 if (ex->is_a(SystemDictionary::Throwable_klass())) {
671 JavaValue result(T_VOID);
672 JavaCalls::call_virtual(&result,
673 ex,
674 SystemDictionary::Throwable_klass(),
675 vmSymbols::printStackTrace_name(),
676 vmSymbols::void_method_signature(),
677 THREAD);
678 // If an exception is thrown in the call it gets thrown away. Not much
679 // we can do with it. The native code that calls this, does not check
680 // for the exception - hence, it might still be in the thread when DestroyVM gets
681 // called, potentially causing a few asserts to trigger - since no pending exception
682 // is expected.
683 CLEAR_PENDING_EXCEPTION;
684 } else {
685 ResourceMark rm(THREAD);
686 jio_fprintf(defaultStream::error_stream(),
687 ". Uncaught exception of type %s.",
688 ex->klass()->external_name());
689 }
690 }
691 }
692
693 HOTSPOT_JNI_EXCEPTIONDESCRIBE_RETURN();
694JNI_END
695
696
697JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env))
698 JNIWrapper("ExceptionClear");
699
700 HOTSPOT_JNI_EXCEPTIONCLEAR_ENTRY(env);
701
702 // The jni code might be using this API to clear java thrown exception.
703 // So just mark jvmti thread exception state as exception caught.
704 JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state();
705 if (state != NULL && state->is_exception_detected()) {
706 state->set_exception_caught();
707 }
708 thread->clear_pending_exception();
709
710 HOTSPOT_JNI_EXCEPTIONCLEAR_RETURN();
711JNI_END
712
713
714JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg))
715 JNIWrapper("FatalError");
716
717 HOTSPOT_JNI_FATALERROR_ENTRY(env, (char *) msg);
718
719 tty->print_cr("FATAL ERROR in native method: %s", msg);
720 thread->print_stack();
721 os::abort(); // Dump core and abort
722JNI_END
723
724
725JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity))
726 JNIWrapper("PushLocalFrame");
727
728 HOTSPOT_JNI_PUSHLOCALFRAME_ENTRY(env, capacity);
729
730 //%note jni_11
731 if (capacity < 0 ||
732 ((MaxJNILocalCapacity > 0) && (capacity > MaxJNILocalCapacity))) {
733 HOTSPOT_JNI_PUSHLOCALFRAME_RETURN((uint32_t)JNI_ERR);
734 return JNI_ERR;
735 }
736 JNIHandleBlock* old_handles = thread->active_handles();
737 JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread);
738 assert(new_handles != NULL, "should not be NULL");
739 new_handles->set_pop_frame_link(old_handles);
740 thread->set_active_handles(new_handles);
741 jint ret = JNI_OK;
742 HOTSPOT_JNI_PUSHLOCALFRAME_RETURN(ret);
743 return ret;
744JNI_END
745
746
747JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result))
748 JNIWrapper("PopLocalFrame");
749
750 HOTSPOT_JNI_POPLOCALFRAME_ENTRY(env, result);
751
752 //%note jni_11
753 Handle result_handle(thread, JNIHandles::resolve(result));
754 JNIHandleBlock* old_handles = thread->active_handles();
755 JNIHandleBlock* new_handles = old_handles->pop_frame_link();
756 if (new_handles != NULL) {
757 // As a sanity check we only release the handle blocks if the pop_frame_link is not NULL.
758 // This way code will still work if PopLocalFrame is called without a corresponding
759 // PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise
760 // the release_block call will release the blocks.
761 thread->set_active_handles(new_handles);
762 old_handles->set_pop_frame_link(NULL); // clear link we won't release new_handles below
763 JNIHandleBlock::release_block(old_handles, thread); // may block
764 result = JNIHandles::make_local(thread, result_handle());
765 }
766 HOTSPOT_JNI_POPLOCALFRAME_RETURN(result);
767 return result;
768JNI_END
769
770
771JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref))
772 JNIWrapper("NewGlobalRef");
773
774 HOTSPOT_JNI_NEWGLOBALREF_ENTRY(env, ref);
775
776 Handle ref_handle(thread, JNIHandles::resolve(ref));
777 jobject ret = JNIHandles::make_global(ref_handle);
778
779 HOTSPOT_JNI_NEWGLOBALREF_RETURN(ret);
780 return ret;
781JNI_END
782
783// Must be JNI_ENTRY (with HandleMark)
784JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref))
785 JNIWrapper("DeleteGlobalRef");
786
787 HOTSPOT_JNI_DELETEGLOBALREF_ENTRY(env, ref);
788
789 JNIHandles::destroy_global(ref);
790
791 HOTSPOT_JNI_DELETEGLOBALREF_RETURN();
792JNI_END
793
794JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj))
795 JNIWrapper("DeleteLocalRef");
796
797 HOTSPOT_JNI_DELETELOCALREF_ENTRY(env, obj);
798
799 JNIHandles::destroy_local(obj);
800
801 HOTSPOT_JNI_DELETELOCALREF_RETURN();
802JNI_END
803
804JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2))
805 JNIWrapper("IsSameObject");
806
807 HOTSPOT_JNI_ISSAMEOBJECT_ENTRY(env, r1, r2);
808
809 jboolean ret = JNIHandles::is_same_object(r1, r2) ? JNI_TRUE : JNI_FALSE;
810
811 HOTSPOT_JNI_ISSAMEOBJECT_RETURN(ret);
812 return ret;
813JNI_END
814
815
816JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref))
817 JNIWrapper("NewLocalRef");
818
819 HOTSPOT_JNI_NEWLOCALREF_ENTRY(env, ref);
820
821 jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref));
822
823 HOTSPOT_JNI_NEWLOCALREF_RETURN(ret);
824 return ret;
825JNI_END
826
827JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity))
828 JNIWrapper("EnsureLocalCapacity");
829
830 HOTSPOT_JNI_ENSURELOCALCAPACITY_ENTRY(env, capacity);
831
832 jint ret;
833 if (capacity >= 0 &&
834 ((MaxJNILocalCapacity <= 0) || (capacity <= MaxJNILocalCapacity))) {
835 ret = JNI_OK;
836 } else {
837 ret = JNI_ERR;
838 }
839
840 HOTSPOT_JNI_ENSURELOCALCAPACITY_RETURN(ret);
841 return ret;
842JNI_END
843
844// Return the Handle Type
845JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj))
846 JNIWrapper("GetObjectRefType");
847
848 HOTSPOT_JNI_GETOBJECTREFTYPE_ENTRY(env, obj);
849
850 jobjectRefType ret = JNIInvalidRefType;
851 if (obj != NULL) {
852 ret = JNIHandles::handle_type(thread, obj);
853 }
854
855 HOTSPOT_JNI_GETOBJECTREFTYPE_RETURN((void *) ret);
856 return ret;
857JNI_END
858
859
860class JNI_ArgumentPusher : public SignatureIterator {
861 protected:
862 JavaCallArguments* _arguments;
863
864 virtual void get_bool () = 0;
865 virtual void get_char () = 0;
866 virtual void get_short () = 0;
867 virtual void get_byte () = 0;
868 virtual void get_int () = 0;
869 virtual void get_long () = 0;
870 virtual void get_float () = 0;
871 virtual void get_double () = 0;
872 virtual void get_object () = 0;
873
874 JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) {
875 this->_return_type = T_ILLEGAL;
876 _arguments = NULL;
877 }
878
879 public:
880 virtual void iterate( uint64_t fingerprint ) = 0;
881
882 void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; }
883
884 inline void do_bool() { if (!is_return_type()) get_bool(); }
885 inline void do_char() { if (!is_return_type()) get_char(); }
886 inline void do_short() { if (!is_return_type()) get_short(); }
887 inline void do_byte() { if (!is_return_type()) get_byte(); }
888 inline void do_int() { if (!is_return_type()) get_int(); }
889 inline void do_long() { if (!is_return_type()) get_long(); }
890 inline void do_float() { if (!is_return_type()) get_float(); }
891 inline void do_double() { if (!is_return_type()) get_double(); }
892 inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); }
893 inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array
894 inline void do_void() { }
895
896 JavaCallArguments* arguments() { return _arguments; }
897 void push_receiver(Handle h) { _arguments->push_oop(h); }
898};
899
900
901class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher {
902 protected:
903 va_list _ap;
904
905 inline void get_bool() {
906 // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and
907 // 0 to JNI_FALSE. Boolean return values from native are normalized the same in
908 // TemplateInterpreterGenerator::generate_result_handler_for and
909 // SharedRuntime::generate_native_wrapper.
910 jboolean b = va_arg(_ap, jint);
911 _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));
912 }
913 inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg
914 inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg
915 inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg
916 inline void get_int() { _arguments->push_int(va_arg(_ap, jint)); }
917
918 // each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests
919
920 inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); }
921 inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg
922 inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); }
923 inline void get_object() { _arguments->push_jobject(va_arg(_ap, jobject)); }
924
925 inline void set_ap(va_list rap) {
926 va_copy(_ap, rap);
927 }
928
929 public:
930 JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap)
931 : JNI_ArgumentPusher(signature) {
932 set_ap(rap);
933 }
934 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap)
935 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
936 set_ap(rap);
937 }
938
939 // Optimized path if we have the bitvector form of signature
940 void iterate( uint64_t fingerprint ) {
941 if (fingerprint == (uint64_t)CONST64(-1)) {
942 SignatureIterator::iterate(); // Must be too many arguments
943 } else {
944 _return_type = (BasicType)((fingerprint >> static_feature_size) &
945 result_feature_mask);
946
947 assert(fingerprint, "Fingerprint should not be 0");
948 fingerprint = fingerprint >> (static_feature_size + result_feature_size);
949 while ( 1 ) {
950 switch ( fingerprint & parameter_feature_mask ) {
951 case bool_parm:
952 get_bool();
953 break;
954 case char_parm:
955 get_char();
956 break;
957 case short_parm:
958 get_short();
959 break;
960 case byte_parm:
961 get_byte();
962 break;
963 case int_parm:
964 get_int();
965 break;
966 case obj_parm:
967 get_object();
968 break;
969 case long_parm:
970 get_long();
971 break;
972 case float_parm:
973 get_float();
974 break;
975 case double_parm:
976 get_double();
977 break;
978 case done_parm:
979 return;
980 break;
981 default:
982 ShouldNotReachHere();
983 break;
984 }
985 fingerprint >>= parameter_feature_size;
986 }
987 }
988 }
989};
990
991
992class JNI_ArgumentPusherArray : public JNI_ArgumentPusher {
993 protected:
994 const jvalue *_ap;
995
996 inline void get_bool() {
997 // Normalize boolean arguments from native code by converting 1-255 to JNI_TRUE and
998 // 0 to JNI_FALSE. Boolean return values from native are normalized the same in
999 // TemplateInterpreterGenerator::generate_result_handler_for and
1000 // SharedRuntime::generate_native_wrapper.
1001 jboolean b = (_ap++)->z;
1002 _arguments->push_int((jint)(b == 0 ? JNI_FALSE : JNI_TRUE));
1003 }
1004 inline void get_char() { _arguments->push_int((jint)(_ap++)->c); }
1005 inline void get_short() { _arguments->push_int((jint)(_ap++)->s); }
1006 inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); }
1007 inline void get_int() { _arguments->push_int((jint)(_ap++)->i); }
1008
1009 inline void get_long() { _arguments->push_long((_ap++)->j); }
1010 inline void get_float() { _arguments->push_float((_ap++)->f); }
1011 inline void get_double() { _arguments->push_double((_ap++)->d);}
1012 inline void get_object() { _arguments->push_jobject((_ap++)->l); }
1013
1014 inline void set_ap(const jvalue *rap) { _ap = rap; }
1015
1016 public:
1017 JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap)
1018 : JNI_ArgumentPusher(signature) {
1019 set_ap(rap);
1020 }
1021 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap)
1022 : JNI_ArgumentPusher(Method::resolve_jmethod_id(method_id)->signature()) {
1023 set_ap(rap);
1024 }
1025
1026 // Optimized path if we have the bitvector form of signature
1027 void iterate( uint64_t fingerprint ) {
1028 if (fingerprint == (uint64_t)CONST64(-1)) {
1029 SignatureIterator::iterate(); // Must be too many arguments
1030 } else {
1031 _return_type = (BasicType)((fingerprint >> static_feature_size) &
1032 result_feature_mask);
1033 assert(fingerprint, "Fingerprint should not be 0");
1034 fingerprint = fingerprint >> (static_feature_size + result_feature_size);
1035 while ( 1 ) {
1036 switch ( fingerprint & parameter_feature_mask ) {
1037 case bool_parm:
1038 get_bool();
1039 break;
1040 case char_parm:
1041 get_char();
1042 break;
1043 case short_parm:
1044 get_short();
1045 break;
1046 case byte_parm:
1047 get_byte();
1048 break;
1049 case int_parm:
1050 get_int();
1051 break;
1052 case obj_parm:
1053 get_object();
1054 break;
1055 case long_parm:
1056 get_long();
1057 break;
1058 case float_parm:
1059 get_float();
1060 break;
1061 case double_parm:
1062 get_double();
1063 break;
1064 case done_parm:
1065 return;
1066 break;
1067 default:
1068 ShouldNotReachHere();
1069 break;
1070 }
1071 fingerprint >>= parameter_feature_size;
1072 }
1073 }
1074 }
1075};
1076
1077
1078enum JNICallType {
1079 JNI_STATIC,
1080 JNI_VIRTUAL,
1081 JNI_NONVIRTUAL
1082};
1083
1084
1085
1086static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
1087 methodHandle method(THREAD, Method::resolve_jmethod_id(method_id));
1088
1089 // Create object to hold arguments for the JavaCall, and associate it with
1090 // the jni parser
1091 ResourceMark rm(THREAD);
1092 int number_of_parameters = method->size_of_parameters();
1093 JavaCallArguments java_args(number_of_parameters);
1094 args->set_java_argument_object(&java_args);
1095
1096 assert(method->is_static(), "method should be static");
1097
1098 // Fill out JavaCallArguments object
1099 args->iterate( Fingerprinter(method).fingerprint() );
1100 // Initialize result type
1101 result->set_type(args->get_ret_type());
1102
1103 // Invoke the method. Result is returned as oop.
1104 JavaCalls::call(result, method, &java_args, CHECK);
1105
1106 // Convert result
1107 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
1108 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
1109 }
1110}
1111
1112
1113static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) {
1114 oop recv = JNIHandles::resolve(receiver);
1115 if (recv == NULL) {
1116 THROW(vmSymbols::java_lang_NullPointerException());
1117 }
1118 Handle h_recv(THREAD, recv);
1119
1120 int number_of_parameters;
1121 Method* selected_method;
1122 {
1123 Method* m = Method::resolve_jmethod_id(method_id);
1124 number_of_parameters = m->size_of_parameters();
1125 Klass* holder = m->method_holder();
1126 if (call_type != JNI_VIRTUAL) {
1127 selected_method = m;
1128 } else if (!m->has_itable_index()) {
1129 // non-interface call -- for that little speed boost, don't handlize
1130 debug_only(NoSafepointVerifier nosafepoint;)
1131 // jni_GetMethodID makes sure class is linked and initialized
1132 // so m should have a valid vtable index.
1133 assert(m->valid_vtable_index(), "no valid vtable index");
1134 int vtbl_index = m->vtable_index();
1135 if (vtbl_index != Method::nonvirtual_vtable_index) {
1136 selected_method = h_recv->klass()->method_at_vtable(vtbl_index);
1137 } else {
1138 // final method
1139 selected_method = m;
1140 }
1141 } else {
1142 // interface call
1143 int itbl_index = m->itable_index();
1144 Klass* k = h_recv->klass();
1145 selected_method = InstanceKlass::cast(k)->method_at_itable(holder, itbl_index, CHECK);
1146 }
1147 }
1148
1149 methodHandle method(THREAD, selected_method);
1150
1151 // Create object to hold arguments for the JavaCall, and associate it with
1152 // the jni parser
1153 ResourceMark rm(THREAD);
1154 JavaCallArguments java_args(number_of_parameters);
1155 args->set_java_argument_object(&java_args);
1156
1157 // handle arguments
1158 assert(!method->is_static(), "method %s should not be static", method->name_and_sig_as_C_string());
1159 args->push_receiver(h_recv); // Push jobject handle
1160
1161 // Fill out JavaCallArguments object
1162 args->iterate( Fingerprinter(method).fingerprint() );
1163 // Initialize result type
1164 result->set_type(args->get_ret_type());
1165
1166 // Invoke the method. Result is returned as oop.
1167 JavaCalls::call(result, method, &java_args, CHECK);
1168
1169 // Convert result
1170 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) {
1171 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject()));
1172 }
1173}
1174
1175
1176static instanceOop alloc_object(jclass clazz, TRAPS) {
1177 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
1178 if (k == NULL) {
1179 ResourceMark rm(THREAD);
1180 THROW_(vmSymbols::java_lang_InstantiationException(), NULL);
1181 }
1182 k->check_valid_for_instantiation(false, CHECK_NULL);
1183 k->initialize(CHECK_NULL);
1184 instanceOop ih = InstanceKlass::cast(k)->allocate_instance(THREAD);
1185 return ih;
1186}
1187
1188DT_RETURN_MARK_DECL(AllocObject, jobject
1189 , HOTSPOT_JNI_ALLOCOBJECT_RETURN(_ret_ref));
1190
1191JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz))
1192 JNIWrapper("AllocObject");
1193
1194 HOTSPOT_JNI_ALLOCOBJECT_ENTRY(env, clazz);
1195
1196 jobject ret = NULL;
1197 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret);
1198
1199 instanceOop i = alloc_object(clazz, CHECK_NULL);
1200 ret = JNIHandles::make_local(env, i);
1201 return ret;
1202JNI_END
1203
1204DT_RETURN_MARK_DECL(NewObjectA, jobject
1205 , HOTSPOT_JNI_NEWOBJECTA_RETURN(_ret_ref));
1206
1207JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args))
1208 JNIWrapper("NewObjectA");
1209
1210 HOTSPOT_JNI_NEWOBJECTA_ENTRY(env, clazz, (uintptr_t) methodID);
1211
1212 jobject obj = NULL;
1213 DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj);
1214
1215 instanceOop i = alloc_object(clazz, CHECK_NULL);
1216 obj = JNIHandles::make_local(env, i);
1217 JavaValue jvalue(T_VOID);
1218 JNI_ArgumentPusherArray ap(methodID, args);
1219 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1220 return obj;
1221JNI_END
1222
1223
1224DT_RETURN_MARK_DECL(NewObjectV, jobject
1225 , HOTSPOT_JNI_NEWOBJECTV_RETURN(_ret_ref));
1226
1227JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args))
1228 JNIWrapper("NewObjectV");
1229
1230 HOTSPOT_JNI_NEWOBJECTV_ENTRY(env, clazz, (uintptr_t) methodID);
1231
1232 jobject obj = NULL;
1233 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj);
1234
1235 instanceOop i = alloc_object(clazz, CHECK_NULL);
1236 obj = JNIHandles::make_local(env, i);
1237 JavaValue jvalue(T_VOID);
1238 JNI_ArgumentPusherVaArg ap(methodID, args);
1239 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1240 return obj;
1241JNI_END
1242
1243
1244DT_RETURN_MARK_DECL(NewObject, jobject
1245 , HOTSPOT_JNI_NEWOBJECT_RETURN(_ret_ref));
1246
1247JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...))
1248 JNIWrapper("NewObject");
1249
1250 HOTSPOT_JNI_NEWOBJECT_ENTRY(env, clazz, (uintptr_t) methodID);
1251
1252 jobject obj = NULL;
1253 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj);
1254
1255 instanceOop i = alloc_object(clazz, CHECK_NULL);
1256 obj = JNIHandles::make_local(env, i);
1257 va_list args;
1258 va_start(args, methodID);
1259 JavaValue jvalue(T_VOID);
1260 JNI_ArgumentPusherVaArg ap(methodID, args);
1261 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL);
1262 va_end(args);
1263 return obj;
1264JNI_END
1265
1266
1267JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj))
1268 JNIWrapper("GetObjectClass");
1269
1270 HOTSPOT_JNI_GETOBJECTCLASS_ENTRY(env, obj);
1271
1272 Klass* k = JNIHandles::resolve_non_null(obj)->klass();
1273 jclass ret =
1274 (jclass) JNIHandles::make_local(env, k->java_mirror());
1275
1276 HOTSPOT_JNI_GETOBJECTCLASS_RETURN(ret);
1277 return ret;
1278JNI_END
1279
1280JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz))
1281 JNIWrapper("IsInstanceOf");
1282
1283 HOTSPOT_JNI_ISINSTANCEOF_ENTRY(env, obj, clazz);
1284
1285 jboolean ret = JNI_TRUE;
1286 if (obj != NULL) {
1287 ret = JNI_FALSE;
1288 Klass* k = java_lang_Class::as_Klass(
1289 JNIHandles::resolve_non_null(clazz));
1290 if (k != NULL) {
1291 ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE;
1292 }
1293 }
1294
1295 HOTSPOT_JNI_ISINSTANCEOF_RETURN(ret);
1296 return ret;
1297JNI_END
1298
1299
1300static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str,
1301 const char *sig, bool is_static, TRAPS) {
1302 // %%%% This code should probably just call into a method in the LinkResolver
1303 //
1304 // The class should have been loaded (we have an instance of the class
1305 // passed in) so the method and signature should already be in the symbol
1306 // table. If they're not there, the method doesn't exist.
1307 const char *name_to_probe = (name_str == NULL)
1308 ? vmSymbols::object_initializer_name()->as_C_string()
1309 : name_str;
1310 TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe));
1311 TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig));
1312
1313 if (name == NULL || signature == NULL) {
1314 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str);
1315 }
1316
1317 Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
1318
1319 // Throw a NoSuchMethodError exception if we have an instance of a
1320 // primitive java.lang.Class
1321 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) {
1322 ResourceMark rm;
1323 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
1324 }
1325
1326 // Make sure class is linked and initialized before handing id's out to
1327 // Method*s.
1328 klass->initialize(CHECK_NULL);
1329
1330 Method* m;
1331 if (name == vmSymbols::object_initializer_name() ||
1332 name == vmSymbols::class_initializer_name()) {
1333 // Never search superclasses for constructors
1334 if (klass->is_instance_klass()) {
1335 m = InstanceKlass::cast(klass)->find_method(name, signature);
1336 } else {
1337 m = NULL;
1338 }
1339 } else {
1340 m = klass->lookup_method(name, signature);
1341 if (m == NULL && klass->is_instance_klass()) {
1342 m = InstanceKlass::cast(klass)->lookup_method_in_ordered_interfaces(name, signature);
1343 }
1344 }
1345 if (m == NULL || (m->is_static() != is_static)) {
1346 ResourceMark rm;
1347 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), err_msg("%s%s.%s%s", is_static ? "static " : "", klass->signature_name(), name_str, sig));
1348 }
1349 return m->jmethod_id();
1350}
1351
1352
1353JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz,
1354 const char *name, const char *sig))
1355 JNIWrapper("GetMethodID");
1356 HOTSPOT_JNI_GETMETHODID_ENTRY(env, clazz, (char *) name, (char *) sig);
1357 jmethodID ret = get_method_id(env, clazz, name, sig, false, thread);
1358 HOTSPOT_JNI_GETMETHODID_RETURN((uintptr_t) ret);
1359 return ret;
1360JNI_END
1361
1362
1363JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz,
1364 const char *name, const char *sig))
1365 JNIWrapper("GetStaticMethodID");
1366 HOTSPOT_JNI_GETSTATICMETHODID_ENTRY(env, (char *) clazz, (char *) name, (char *)sig);
1367 jmethodID ret = get_method_id(env, clazz, name, sig, true, thread);
1368 HOTSPOT_JNI_GETSTATICMETHODID_RETURN((uintptr_t) ret);
1369 return ret;
1370JNI_END
1371
1372
1373
1374//
1375// Calling Methods
1376//
1377
1378
1379#define DEFINE_CALLMETHOD(ResultType, Result, Tag \
1380 , EntryProbe, ReturnProbe) \
1381\
1382 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType \
1383 , ReturnProbe); \
1384\
1385JNI_ENTRY(ResultType, \
1386 jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \
1387 JNIWrapper("Call" XSTR(Result) "Method"); \
1388\
1389 EntryProbe; \
1390 ResultType ret = 0;\
1391 DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \
1392 (const ResultType&)ret);\
1393\
1394 va_list args; \
1395 va_start(args, methodID); \
1396 JavaValue jvalue(Tag); \
1397 JNI_ArgumentPusherVaArg ap(methodID, args); \
1398 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
1399 va_end(args); \
1400 ret = jvalue.get_##ResultType(); \
1401 return ret;\
1402JNI_END
1403
1404// the runtime type of subword integral basic types is integer
1405DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN
1406 , HOTSPOT_JNI_CALLBOOLEANMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1407 HOTSPOT_JNI_CALLBOOLEANMETHOD_RETURN(_ret_ref))
1408DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE
1409 , HOTSPOT_JNI_CALLBYTEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1410 HOTSPOT_JNI_CALLBYTEMETHOD_RETURN(_ret_ref))
1411DEFINE_CALLMETHOD(jchar, Char, T_CHAR
1412 , HOTSPOT_JNI_CALLCHARMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1413 HOTSPOT_JNI_CALLCHARMETHOD_RETURN(_ret_ref))
1414DEFINE_CALLMETHOD(jshort, Short, T_SHORT
1415 , HOTSPOT_JNI_CALLSHORTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1416 HOTSPOT_JNI_CALLSHORTMETHOD_RETURN(_ret_ref))
1417
1418DEFINE_CALLMETHOD(jobject, Object, T_OBJECT
1419 , HOTSPOT_JNI_CALLOBJECTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1420 HOTSPOT_JNI_CALLOBJECTMETHOD_RETURN(_ret_ref))
1421DEFINE_CALLMETHOD(jint, Int, T_INT,
1422 HOTSPOT_JNI_CALLINTMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1423 HOTSPOT_JNI_CALLINTMETHOD_RETURN(_ret_ref))
1424DEFINE_CALLMETHOD(jlong, Long, T_LONG
1425 , HOTSPOT_JNI_CALLLONGMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1426 HOTSPOT_JNI_CALLLONGMETHOD_RETURN(_ret_ref))
1427// Float and double probes don't return value because dtrace doesn't currently support it
1428DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT
1429 , HOTSPOT_JNI_CALLFLOATMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1430 HOTSPOT_JNI_CALLFLOATMETHOD_RETURN())
1431DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE
1432 , HOTSPOT_JNI_CALLDOUBLEMETHOD_ENTRY(env, obj, (uintptr_t)methodID),
1433 HOTSPOT_JNI_CALLDOUBLEMETHOD_RETURN())
1434
1435#define DEFINE_CALLMETHODV(ResultType, Result, Tag \
1436 , EntryProbe, ReturnProbe) \
1437\
1438 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType \
1439 , ReturnProbe); \
1440\
1441JNI_ENTRY(ResultType, \
1442 jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \
1443 JNIWrapper("Call" XSTR(Result) "MethodV"); \
1444\
1445 EntryProbe;\
1446 ResultType ret = 0;\
1447 DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \
1448 (const ResultType&)ret);\
1449\
1450 JavaValue jvalue(Tag); \
1451 JNI_ArgumentPusherVaArg ap(methodID, args); \
1452 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
1453 ret = jvalue.get_##ResultType(); \
1454 return ret;\
1455JNI_END
1456
1457// the runtime type of subword integral basic types is integer
1458DEFINE_CALLMETHODV(jboolean, Boolean, T_BOOLEAN
1459 , HOTSPOT_JNI_CALLBOOLEANMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1460 HOTSPOT_JNI_CALLBOOLEANMETHODV_RETURN(_ret_ref))
1461DEFINE_CALLMETHODV(jbyte, Byte, T_BYTE
1462 , HOTSPOT_JNI_CALLBYTEMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1463 HOTSPOT_JNI_CALLBYTEMETHODV_RETURN(_ret_ref))
1464DEFINE_CALLMETHODV(jchar, Char, T_CHAR
1465 , HOTSPOT_JNI_CALLCHARMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1466 HOTSPOT_JNI_CALLCHARMETHODV_RETURN(_ret_ref))
1467DEFINE_CALLMETHODV(jshort, Short, T_SHORT
1468 , HOTSPOT_JNI_CALLSHORTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1469 HOTSPOT_JNI_CALLSHORTMETHODV_RETURN(_ret_ref))
1470
1471DEFINE_CALLMETHODV(jobject, Object, T_OBJECT
1472 , HOTSPOT_JNI_CALLOBJECTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1473 HOTSPOT_JNI_CALLOBJECTMETHODV_RETURN(_ret_ref))
1474DEFINE_CALLMETHODV(jint, Int, T_INT,
1475 HOTSPOT_JNI_CALLINTMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1476 HOTSPOT_JNI_CALLINTMETHODV_RETURN(_ret_ref))
1477DEFINE_CALLMETHODV(jlong, Long, T_LONG
1478 , HOTSPOT_JNI_CALLLONGMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1479 HOTSPOT_JNI_CALLLONGMETHODV_RETURN(_ret_ref))
1480// Float and double probes don't return value because dtrace doesn't currently support it
1481DEFINE_CALLMETHODV(jfloat, Float, T_FLOAT
1482 , HOTSPOT_JNI_CALLFLOATMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1483 HOTSPOT_JNI_CALLFLOATMETHODV_RETURN())
1484DEFINE_CALLMETHODV(jdouble, Double, T_DOUBLE
1485 , HOTSPOT_JNI_CALLDOUBLEMETHODV_ENTRY(env, obj, (uintptr_t)methodID),
1486 HOTSPOT_JNI_CALLDOUBLEMETHODV_RETURN())
1487
1488#define DEFINE_CALLMETHODA(ResultType, Result, Tag \
1489 , EntryProbe, ReturnProbe) \
1490\
1491 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType \
1492 , ReturnProbe); \
1493\
1494JNI_ENTRY(ResultType, \
1495 jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \
1496 JNIWrapper("Call" XSTR(Result) "MethodA"); \
1497 EntryProbe; \
1498 ResultType ret = 0;\
1499 DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \
1500 (const ResultType&)ret);\
1501\
1502 JavaValue jvalue(Tag); \
1503 JNI_ArgumentPusherArray ap(methodID, args); \
1504 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \
1505 ret = jvalue.get_##ResultType(); \
1506 return ret;\
1507JNI_END
1508
1509// the runtime type of subword integral basic types is integer
1510DEFINE_CALLMETHODA(jboolean, Boolean, T_BOOLEAN
1511 , HOTSPOT_JNI_CALLBOOLEANMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1512 HOTSPOT_JNI_CALLBOOLEANMETHODA_RETURN(_ret_ref))
1513DEFINE_CALLMETHODA(jbyte, Byte, T_BYTE
1514 , HOTSPOT_JNI_CALLBYTEMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1515 HOTSPOT_JNI_CALLBYTEMETHODA_RETURN(_ret_ref))
1516DEFINE_CALLMETHODA(jchar, Char, T_CHAR
1517 , HOTSPOT_JNI_CALLCHARMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1518 HOTSPOT_JNI_CALLCHARMETHODA_RETURN(_ret_ref))
1519DEFINE_CALLMETHODA(jshort, Short, T_SHORT
1520 , HOTSPOT_JNI_CALLSHORTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1521 HOTSPOT_JNI_CALLSHORTMETHODA_RETURN(_ret_ref))
1522
1523DEFINE_CALLMETHODA(jobject, Object, T_OBJECT
1524 , HOTSPOT_JNI_CALLOBJECTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1525 HOTSPOT_JNI_CALLOBJECTMETHODA_RETURN(_ret_ref))
1526DEFINE_CALLMETHODA(jint, Int, T_INT,
1527 HOTSPOT_JNI_CALLINTMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1528 HOTSPOT_JNI_CALLINTMETHODA_RETURN(_ret_ref))
1529DEFINE_CALLMETHODA(jlong, Long, T_LONG
1530 , HOTSPOT_JNI_CALLLONGMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1531 HOTSPOT_JNI_CALLLONGMETHODA_RETURN(_ret_ref))
1532// Float and double probes don't return value because dtrace doesn't currently support it
1533DEFINE_CALLMETHODA(jfloat, Float, T_FLOAT
1534 , HOTSPOT_JNI_CALLFLOATMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1535 HOTSPOT_JNI_CALLFLOATMETHODA_RETURN())
1536DEFINE_CALLMETHODA(jdouble, Double, T_DOUBLE
1537 , HOTSPOT_JNI_CALLDOUBLEMETHODA_ENTRY(env, obj, (uintptr_t)methodID),
1538 HOTSPOT_JNI_CALLDOUBLEMETHODA_RETURN())
1539
1540DT_VOID_RETURN_MARK_DECL(CallVoidMethod, HOTSPOT_JNI_CALLVOIDMETHOD_RETURN());
1541DT_VOID_RETURN_MARK_DECL(CallVoidMethodV, HOTSPOT_JNI_CALLVOIDMETHODV_RETURN());
1542DT_VOID_RETURN_MARK_DECL(CallVoidMethodA, HOTSPOT_JNI_CALLVOIDMETHODA_RETURN());
1543
1544
1545JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...))
1546 JNIWrapper("CallVoidMethod");
1547 HOTSPOT_JNI_CALLVOIDMETHOD_ENTRY(env, obj, (uintptr_t) methodID);
1548 DT_VOID_RETURN_MARK(CallVoidMethod);
1549
1550 va_list args;
1551 va_start(args, methodID);
1552 JavaValue jvalue(T_VOID);
1553 JNI_ArgumentPusherVaArg ap(methodID, args);
1554 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
1555 va_end(args);
1556JNI_END
1557
1558
1559JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args))
1560 JNIWrapper("CallVoidMethodV");
1561 HOTSPOT_JNI_CALLVOIDMETHODV_ENTRY(env, obj, (uintptr_t) methodID);
1562 DT_VOID_RETURN_MARK(CallVoidMethodV);
1563
1564 JavaValue jvalue(T_VOID);
1565 JNI_ArgumentPusherVaArg ap(methodID, args);
1566 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
1567JNI_END
1568
1569
1570JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args))
1571 JNIWrapper("CallVoidMethodA");
1572 HOTSPOT_JNI_CALLVOIDMETHODA_ENTRY(env, obj, (uintptr_t) methodID);
1573 DT_VOID_RETURN_MARK(CallVoidMethodA);
1574
1575 JavaValue jvalue(T_VOID);
1576 JNI_ArgumentPusherArray ap(methodID, args);
1577 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK);
1578JNI_END
1579
1580
1581
1582#define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag \
1583 , EntryProbe, ReturnProbe) \
1584\
1585 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType \
1586 , ReturnProbe);\
1587\
1588JNI_ENTRY(ResultType, \
1589 jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \
1590 JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \
1591\
1592 EntryProbe;\
1593 ResultType ret;\
1594 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \
1595 (const ResultType&)ret);\
1596\
1597 va_list args; \
1598 va_start(args, methodID); \
1599 JavaValue jvalue(Tag); \
1600 JNI_ArgumentPusherVaArg ap(methodID, args); \
1601 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
1602 va_end(args); \
1603 ret = jvalue.get_##ResultType(); \
1604 return ret;\
1605JNI_END
1606
1607// the runtime type of subword integral basic types is integer
1608DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN
1609 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1610 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHOD_RETURN(_ret_ref))
1611DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE
1612 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1613 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHOD_RETURN(_ret_ref))
1614DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR
1615 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1616 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHOD_RETURN(_ret_ref))
1617DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT
1618 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1619 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHOD_RETURN(_ret_ref))
1620
1621DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT
1622 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1623 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHOD_RETURN(_ret_ref))
1624DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT
1625 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1626 HOTSPOT_JNI_CALLNONVIRTUALINTMETHOD_RETURN(_ret_ref))
1627DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG
1628 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1629// Float and double probes don't return value because dtrace doesn't currently support it
1630 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHOD_RETURN(_ret_ref))
1631DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT
1632 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1633 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHOD_RETURN())
1634DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE
1635 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_ENTRY(env, obj, cls, (uintptr_t)methodID),
1636 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHOD_RETURN())
1637
1638#define DEFINE_CALLNONVIRTUALMETHODV(ResultType, Result, Tag \
1639 , EntryProbe, ReturnProbe) \
1640\
1641 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType \
1642 , ReturnProbe);\
1643\
1644JNI_ENTRY(ResultType, \
1645 jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \
1646 JNIWrapper("CallNonvitual" XSTR(Result) "MethodV"); \
1647\
1648 EntryProbe;\
1649 ResultType ret;\
1650 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \
1651 (const ResultType&)ret);\
1652\
1653 JavaValue jvalue(Tag); \
1654 JNI_ArgumentPusherVaArg ap(methodID, args); \
1655 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
1656 ret = jvalue.get_##ResultType(); \
1657 return ret;\
1658JNI_END
1659
1660// the runtime type of subword integral basic types is integer
1661DEFINE_CALLNONVIRTUALMETHODV(jboolean, Boolean, T_BOOLEAN
1662 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1663 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODV_RETURN(_ret_ref))
1664DEFINE_CALLNONVIRTUALMETHODV(jbyte, Byte, T_BYTE
1665 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1666 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODV_RETURN(_ret_ref))
1667DEFINE_CALLNONVIRTUALMETHODV(jchar, Char, T_CHAR
1668 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1669 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODV_RETURN(_ret_ref))
1670DEFINE_CALLNONVIRTUALMETHODV(jshort, Short, T_SHORT
1671 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1672 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODV_RETURN(_ret_ref))
1673
1674DEFINE_CALLNONVIRTUALMETHODV(jobject, Object, T_OBJECT
1675 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1676 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODV_RETURN(_ret_ref))
1677DEFINE_CALLNONVIRTUALMETHODV(jint, Int, T_INT
1678 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1679 HOTSPOT_JNI_CALLNONVIRTUALINTMETHODV_RETURN(_ret_ref))
1680DEFINE_CALLNONVIRTUALMETHODV(jlong, Long, T_LONG
1681 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1682// Float and double probes don't return value because dtrace doesn't currently support it
1683 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODV_RETURN(_ret_ref))
1684DEFINE_CALLNONVIRTUALMETHODV(jfloat, Float, T_FLOAT
1685 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1686 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODV_RETURN())
1687DEFINE_CALLNONVIRTUALMETHODV(jdouble, Double, T_DOUBLE
1688 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_ENTRY(env, obj, cls, (uintptr_t)methodID),
1689 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODV_RETURN())
1690
1691#define DEFINE_CALLNONVIRTUALMETHODA(ResultType, Result, Tag \
1692 , EntryProbe, ReturnProbe) \
1693\
1694 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType \
1695 , ReturnProbe);\
1696\
1697JNI_ENTRY(ResultType, \
1698 jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \
1699 JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \
1700\
1701 EntryProbe;\
1702 ResultType ret;\
1703 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \
1704 (const ResultType&)ret);\
1705\
1706 JavaValue jvalue(Tag); \
1707 JNI_ArgumentPusherArray ap(methodID, args); \
1708 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \
1709 ret = jvalue.get_##ResultType(); \
1710 return ret;\
1711JNI_END
1712
1713// the runtime type of subword integral basic types is integer
1714DEFINE_CALLNONVIRTUALMETHODA(jboolean, Boolean, T_BOOLEAN
1715 , HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1716 HOTSPOT_JNI_CALLNONVIRTUALBOOLEANMETHODA_RETURN(_ret_ref))
1717DEFINE_CALLNONVIRTUALMETHODA(jbyte, Byte, T_BYTE
1718 , HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1719 HOTSPOT_JNI_CALLNONVIRTUALBYTEMETHODA_RETURN(_ret_ref))
1720DEFINE_CALLNONVIRTUALMETHODA(jchar, Char, T_CHAR
1721 , HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1722 HOTSPOT_JNI_CALLNONVIRTUALCHARMETHODA_RETURN(_ret_ref))
1723DEFINE_CALLNONVIRTUALMETHODA(jshort, Short, T_SHORT
1724 , HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1725 HOTSPOT_JNI_CALLNONVIRTUALSHORTMETHODA_RETURN(_ret_ref))
1726
1727DEFINE_CALLNONVIRTUALMETHODA(jobject, Object, T_OBJECT
1728 , HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1729 HOTSPOT_JNI_CALLNONVIRTUALOBJECTMETHODA_RETURN(_ret_ref))
1730DEFINE_CALLNONVIRTUALMETHODA(jint, Int, T_INT
1731 , HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1732 HOTSPOT_JNI_CALLNONVIRTUALINTMETHODA_RETURN(_ret_ref))
1733DEFINE_CALLNONVIRTUALMETHODA(jlong, Long, T_LONG
1734 , HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1735// Float and double probes don't return value because dtrace doesn't currently support it
1736 HOTSPOT_JNI_CALLNONVIRTUALLONGMETHODA_RETURN(_ret_ref))
1737DEFINE_CALLNONVIRTUALMETHODA(jfloat, Float, T_FLOAT
1738 , HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1739 HOTSPOT_JNI_CALLNONVIRTUALFLOATMETHODA_RETURN())
1740DEFINE_CALLNONVIRTUALMETHODA(jdouble, Double, T_DOUBLE
1741 , HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_ENTRY(env, obj, cls, (uintptr_t)methodID),
1742 HOTSPOT_JNI_CALLNONVIRTUALDOUBLEMETHODA_RETURN())
1743
1744DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod
1745 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_RETURN());
1746DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV
1747 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_RETURN());
1748DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA
1749 , HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_RETURN());
1750
1751JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...))
1752 JNIWrapper("CallNonvirtualVoidMethod");
1753
1754 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHOD_ENTRY(env, obj, cls, (uintptr_t) methodID);
1755 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod);
1756
1757 va_list args;
1758 va_start(args, methodID);
1759 JavaValue jvalue(T_VOID);
1760 JNI_ArgumentPusherVaArg ap(methodID, args);
1761 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
1762 va_end(args);
1763JNI_END
1764
1765
1766JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args))
1767 JNIWrapper("CallNonvirtualVoidMethodV");
1768
1769 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODV_ENTRY(
1770 env, obj, cls, (uintptr_t) methodID);
1771 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV);
1772
1773 JavaValue jvalue(T_VOID);
1774 JNI_ArgumentPusherVaArg ap(methodID, args);
1775 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
1776JNI_END
1777
1778
1779JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args))
1780 JNIWrapper("CallNonvirtualVoidMethodA");
1781 HOTSPOT_JNI_CALLNONVIRTUALVOIDMETHODA_ENTRY(
1782 env, obj, cls, (uintptr_t) methodID);
1783 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA);
1784 JavaValue jvalue(T_VOID);
1785 JNI_ArgumentPusherArray ap(methodID, args);
1786 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK);
1787JNI_END
1788
1789
1790
1791#define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag \
1792 , EntryProbe, ResultProbe) \
1793\
1794 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType \
1795 , ResultProbe); \
1796\
1797JNI_ENTRY(ResultType, \
1798 jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \
1799 JNIWrapper("CallStatic" XSTR(Result) "Method"); \
1800\
1801 EntryProbe; \
1802 ResultType ret = 0;\
1803 DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \
1804 (const ResultType&)ret);\
1805\
1806 va_list args; \
1807 va_start(args, methodID); \
1808 JavaValue jvalue(Tag); \
1809 JNI_ArgumentPusherVaArg ap(methodID, args); \
1810 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
1811 va_end(args); \
1812 ret = jvalue.get_##ResultType(); \
1813 return ret;\
1814JNI_END
1815
1816// the runtime type of subword integral basic types is integer
1817DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN
1818 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1819 HOTSPOT_JNI_CALLSTATICBOOLEANMETHOD_RETURN(_ret_ref));
1820DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE
1821 , HOTSPOT_JNI_CALLSTATICBYTEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1822 HOTSPOT_JNI_CALLSTATICBYTEMETHOD_RETURN(_ret_ref));
1823DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR
1824 , HOTSPOT_JNI_CALLSTATICCHARMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1825 HOTSPOT_JNI_CALLSTATICCHARMETHOD_RETURN(_ret_ref));
1826DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT
1827 , HOTSPOT_JNI_CALLSTATICSHORTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1828 HOTSPOT_JNI_CALLSTATICSHORTMETHOD_RETURN(_ret_ref));
1829
1830DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT
1831 , HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1832 HOTSPOT_JNI_CALLSTATICOBJECTMETHOD_RETURN(_ret_ref));
1833DEFINE_CALLSTATICMETHOD(jint, Int, T_INT
1834 , HOTSPOT_JNI_CALLSTATICINTMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1835 HOTSPOT_JNI_CALLSTATICINTMETHOD_RETURN(_ret_ref));
1836DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG
1837 , HOTSPOT_JNI_CALLSTATICLONGMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1838 HOTSPOT_JNI_CALLSTATICLONGMETHOD_RETURN(_ret_ref));
1839// Float and double probes don't return value because dtrace doesn't currently support it
1840DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT
1841 , HOTSPOT_JNI_CALLSTATICFLOATMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1842 HOTSPOT_JNI_CALLSTATICFLOATMETHOD_RETURN());
1843DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE
1844 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_ENTRY(env, cls, (uintptr_t)methodID),
1845 HOTSPOT_JNI_CALLSTATICDOUBLEMETHOD_RETURN());
1846
1847#define DEFINE_CALLSTATICMETHODV(ResultType, Result, Tag \
1848 , EntryProbe, ResultProbe) \
1849\
1850 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType \
1851 , ResultProbe); \
1852\
1853JNI_ENTRY(ResultType, \
1854 jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \
1855 JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \
1856\
1857 EntryProbe; \
1858 ResultType ret = 0;\
1859 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \
1860 (const ResultType&)ret);\
1861\
1862 JavaValue jvalue(Tag); \
1863 JNI_ArgumentPusherVaArg ap(methodID, args); \
1864 /* Make sure class is initialized before trying to invoke its method */ \
1865 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); \
1866 k->initialize(CHECK_0); \
1867 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
1868 va_end(args); \
1869 ret = jvalue.get_##ResultType(); \
1870 return ret;\
1871JNI_END
1872
1873// the runtime type of subword integral basic types is integer
1874DEFINE_CALLSTATICMETHODV(jboolean, Boolean, T_BOOLEAN
1875 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1876 HOTSPOT_JNI_CALLSTATICBOOLEANMETHODV_RETURN(_ret_ref));
1877DEFINE_CALLSTATICMETHODV(jbyte, Byte, T_BYTE
1878 , HOTSPOT_JNI_CALLSTATICBYTEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1879 HOTSPOT_JNI_CALLSTATICBYTEMETHODV_RETURN(_ret_ref));
1880DEFINE_CALLSTATICMETHODV(jchar, Char, T_CHAR
1881 , HOTSPOT_JNI_CALLSTATICCHARMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1882 HOTSPOT_JNI_CALLSTATICCHARMETHODV_RETURN(_ret_ref));
1883DEFINE_CALLSTATICMETHODV(jshort, Short, T_SHORT
1884 , HOTSPOT_JNI_CALLSTATICSHORTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1885 HOTSPOT_JNI_CALLSTATICSHORTMETHODV_RETURN(_ret_ref));
1886
1887DEFINE_CALLSTATICMETHODV(jobject, Object, T_OBJECT
1888 , HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1889 HOTSPOT_JNI_CALLSTATICOBJECTMETHODV_RETURN(_ret_ref));
1890DEFINE_CALLSTATICMETHODV(jint, Int, T_INT
1891 , HOTSPOT_JNI_CALLSTATICINTMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1892 HOTSPOT_JNI_CALLSTATICINTMETHODV_RETURN(_ret_ref));
1893DEFINE_CALLSTATICMETHODV(jlong, Long, T_LONG
1894 , HOTSPOT_JNI_CALLSTATICLONGMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1895 HOTSPOT_JNI_CALLSTATICLONGMETHODV_RETURN(_ret_ref));
1896// Float and double probes don't return value because dtrace doesn't currently support it
1897DEFINE_CALLSTATICMETHODV(jfloat, Float, T_FLOAT
1898 , HOTSPOT_JNI_CALLSTATICFLOATMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1899 HOTSPOT_JNI_CALLSTATICFLOATMETHODV_RETURN());
1900DEFINE_CALLSTATICMETHODV(jdouble, Double, T_DOUBLE
1901 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_ENTRY(env, cls, (uintptr_t)methodID),
1902 HOTSPOT_JNI_CALLSTATICDOUBLEMETHODV_RETURN());
1903
1904#define DEFINE_CALLSTATICMETHODA(ResultType, Result, Tag \
1905 , EntryProbe, ResultProbe) \
1906\
1907 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType \
1908 , ResultProbe); \
1909\
1910JNI_ENTRY(ResultType, \
1911 jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \
1912 JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \
1913\
1914 EntryProbe; \
1915 ResultType ret = 0;\
1916 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \
1917 (const ResultType&)ret);\
1918\
1919 JavaValue jvalue(Tag); \
1920 JNI_ArgumentPusherArray ap(methodID, args); \
1921 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \
1922 ret = jvalue.get_##ResultType(); \
1923 return ret;\
1924JNI_END
1925
1926// the runtime type of subword integral basic types is integer
1927DEFINE_CALLSTATICMETHODA(jboolean, Boolean, T_BOOLEAN
1928 , HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1929 HOTSPOT_JNI_CALLSTATICBOOLEANMETHODA_RETURN(_ret_ref));
1930DEFINE_CALLSTATICMETHODA(jbyte, Byte, T_BYTE
1931 , HOTSPOT_JNI_CALLSTATICBYTEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1932 HOTSPOT_JNI_CALLSTATICBYTEMETHODA_RETURN(_ret_ref));
1933DEFINE_CALLSTATICMETHODA(jchar, Char, T_CHAR
1934 , HOTSPOT_JNI_CALLSTATICCHARMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1935 HOTSPOT_JNI_CALLSTATICCHARMETHODA_RETURN(_ret_ref));
1936DEFINE_CALLSTATICMETHODA(jshort, Short, T_SHORT
1937 , HOTSPOT_JNI_CALLSTATICSHORTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1938 HOTSPOT_JNI_CALLSTATICSHORTMETHODA_RETURN(_ret_ref));
1939
1940DEFINE_CALLSTATICMETHODA(jobject, Object, T_OBJECT
1941 , HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1942 HOTSPOT_JNI_CALLSTATICOBJECTMETHODA_RETURN(_ret_ref));
1943DEFINE_CALLSTATICMETHODA(jint, Int, T_INT
1944 , HOTSPOT_JNI_CALLSTATICINTMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1945 HOTSPOT_JNI_CALLSTATICINTMETHODA_RETURN(_ret_ref));
1946DEFINE_CALLSTATICMETHODA(jlong, Long, T_LONG
1947 , HOTSPOT_JNI_CALLSTATICLONGMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1948 HOTSPOT_JNI_CALLSTATICLONGMETHODA_RETURN(_ret_ref));
1949// Float and double probes don't return value because dtrace doesn't currently support it
1950DEFINE_CALLSTATICMETHODA(jfloat, Float, T_FLOAT
1951 , HOTSPOT_JNI_CALLSTATICFLOATMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1952 HOTSPOT_JNI_CALLSTATICFLOATMETHODA_RETURN());
1953DEFINE_CALLSTATICMETHODA(jdouble, Double, T_DOUBLE
1954 , HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_ENTRY(env, cls, (uintptr_t)methodID),
1955 HOTSPOT_JNI_CALLSTATICDOUBLEMETHODA_RETURN());
1956
1957DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod
1958 , HOTSPOT_JNI_CALLSTATICVOIDMETHOD_RETURN());
1959DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV
1960 , HOTSPOT_JNI_CALLSTATICVOIDMETHODV_RETURN());
1961DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA
1962 , HOTSPOT_JNI_CALLSTATICVOIDMETHODA_RETURN());
1963
1964JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...))
1965 JNIWrapper("CallStaticVoidMethod");
1966 HOTSPOT_JNI_CALLSTATICVOIDMETHOD_ENTRY(env, cls, (uintptr_t) methodID);
1967 DT_VOID_RETURN_MARK(CallStaticVoidMethod);
1968
1969 va_list args;
1970 va_start(args, methodID);
1971 JavaValue jvalue(T_VOID);
1972 JNI_ArgumentPusherVaArg ap(methodID, args);
1973 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
1974 va_end(args);
1975JNI_END
1976
1977
1978JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args))
1979 JNIWrapper("CallStaticVoidMethodV");
1980 HOTSPOT_JNI_CALLSTATICVOIDMETHODV_ENTRY(env, cls, (uintptr_t) methodID);
1981 DT_VOID_RETURN_MARK(CallStaticVoidMethodV);
1982
1983 JavaValue jvalue(T_VOID);
1984 JNI_ArgumentPusherVaArg ap(methodID, args);
1985 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
1986JNI_END
1987
1988
1989JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args))
1990 JNIWrapper("CallStaticVoidMethodA");
1991 HOTSPOT_JNI_CALLSTATICVOIDMETHODA_ENTRY(env, cls, (uintptr_t) methodID);
1992 DT_VOID_RETURN_MARK(CallStaticVoidMethodA);
1993
1994 JavaValue jvalue(T_VOID);
1995 JNI_ArgumentPusherArray ap(methodID, args);
1996 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK);
1997JNI_END
1998
1999
2000//
2001// Accessing Fields
2002//
2003
2004
2005DT_RETURN_MARK_DECL(GetFieldID, jfieldID
2006 , HOTSPOT_JNI_GETFIELDID_RETURN((uintptr_t)_ret_ref));
2007
2008JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz,
2009 const char *name, const char *sig))
2010 JNIWrapper("GetFieldID");
2011 HOTSPOT_JNI_GETFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig);
2012 jfieldID ret = 0;
2013 DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret);
2014
2015 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
2016
2017 // The class should have been loaded (we have an instance of the class
2018 // passed in) so the field and signature should already be in the symbol
2019 // table. If they're not there, the field doesn't exist.
2020 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
2021 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
2022 if (fieldname == NULL || signame == NULL) {
2023 ResourceMark rm;
2024 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
2025 }
2026
2027 // Make sure class is initialized before handing id's out to fields
2028 k->initialize(CHECK_NULL);
2029
2030 fieldDescriptor fd;
2031 if (!k->is_instance_klass() ||
2032 !InstanceKlass::cast(k)->find_field(fieldname, signame, false, &fd)) {
2033 ResourceMark rm;
2034 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), err_msg("%s.%s %s", k->external_name(), name, sig));
2035 }
2036
2037 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop
2038 // It may also have hash bits for k, if VerifyJNIFields is turned on.
2039 ret = jfieldIDWorkaround::to_instance_jfieldID(k, fd.offset());
2040 return ret;
2041JNI_END
2042
2043
2044JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID))
2045 JNIWrapper("GetObjectField");
2046 HOTSPOT_JNI_GETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID);
2047 oop o = JNIHandles::resolve_non_null(obj);
2048 Klass* k = o->klass();
2049 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
2050 // Keep JVMTI addition small and only check enabled flag here.
2051 // jni_GetField_probe() assumes that is okay to create handles.
2052 if (JvmtiExport::should_post_field_access()) {
2053 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false);
2054 }
2055 oop loaded_obj = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(o, offset);
2056 jobject ret = JNIHandles::make_local(env, loaded_obj);
2057 HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret);
2058 return ret;
2059JNI_END
2060
2061
2062
2063#define DEFINE_GETFIELD(Return,Fieldname,Result \
2064 , EntryProbe, ReturnProbe) \
2065\
2066 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return \
2067 , ReturnProbe); \
2068\
2069JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \
2070 JNIWrapper("Get" XSTR(Result) "Field"); \
2071\
2072 EntryProbe; \
2073 Return ret = 0;\
2074 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\
2075\
2076 oop o = JNIHandles::resolve_non_null(obj); \
2077 Klass* k = o->klass(); \
2078 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
2079 /* Keep JVMTI addition small and only check enabled flag here. */ \
2080 /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \
2081 /* and creates a ResetNoHandleMark. */ \
2082 if (JvmtiExport::should_post_field_access()) { \
2083 o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \
2084 } \
2085 ret = o->Fieldname##_field(offset); \
2086 return ret; \
2087JNI_END
2088
2089DEFINE_GETFIELD(jboolean, bool, Boolean
2090 , HOTSPOT_JNI_GETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2091 HOTSPOT_JNI_GETBOOLEANFIELD_RETURN(_ret_ref))
2092DEFINE_GETFIELD(jbyte, byte, Byte
2093 , HOTSPOT_JNI_GETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2094 HOTSPOT_JNI_GETBYTEFIELD_RETURN(_ret_ref))
2095DEFINE_GETFIELD(jchar, char, Char
2096 , HOTSPOT_JNI_GETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2097 HOTSPOT_JNI_GETCHARFIELD_RETURN(_ret_ref))
2098DEFINE_GETFIELD(jshort, short, Short
2099 , HOTSPOT_JNI_GETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2100 HOTSPOT_JNI_GETSHORTFIELD_RETURN(_ret_ref))
2101DEFINE_GETFIELD(jint, int, Int
2102 , HOTSPOT_JNI_GETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2103 HOTSPOT_JNI_GETINTFIELD_RETURN(_ret_ref))
2104DEFINE_GETFIELD(jlong, long, Long
2105 , HOTSPOT_JNI_GETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2106 HOTSPOT_JNI_GETLONGFIELD_RETURN(_ret_ref))
2107// Float and double probes don't return value because dtrace doesn't currently support it
2108DEFINE_GETFIELD(jfloat, float, Float
2109 , HOTSPOT_JNI_GETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2110 HOTSPOT_JNI_GETFLOATFIELD_RETURN())
2111DEFINE_GETFIELD(jdouble, double, Double
2112 , HOTSPOT_JNI_GETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2113 HOTSPOT_JNI_GETDOUBLEFIELD_RETURN())
2114
2115address jni_GetBooleanField_addr() {
2116 return (address)jni_GetBooleanField;
2117}
2118address jni_GetByteField_addr() {
2119 return (address)jni_GetByteField;
2120}
2121address jni_GetCharField_addr() {
2122 return (address)jni_GetCharField;
2123}
2124address jni_GetShortField_addr() {
2125 return (address)jni_GetShortField;
2126}
2127address jni_GetIntField_addr() {
2128 return (address)jni_GetIntField;
2129}
2130address jni_GetLongField_addr() {
2131 return (address)jni_GetLongField;
2132}
2133address jni_GetFloatField_addr() {
2134 return (address)jni_GetFloatField;
2135}
2136address jni_GetDoubleField_addr() {
2137 return (address)jni_GetDoubleField;
2138}
2139
2140JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value))
2141 JNIWrapper("SetObjectField");
2142 HOTSPOT_JNI_SETOBJECTFIELD_ENTRY(env, obj, (uintptr_t) fieldID, value);
2143 oop o = JNIHandles::resolve_non_null(obj);
2144 Klass* k = o->klass();
2145 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
2146 // Keep JVMTI addition small and only check enabled flag here.
2147 // jni_SetField_probe_nh() assumes that is not okay to create handles
2148 // and creates a ResetNoHandleMark.
2149 if (JvmtiExport::should_post_field_modification()) {
2150 jvalue field_value;
2151 field_value.l = value;
2152 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value);
2153 }
2154 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(o, offset, JNIHandles::resolve(value));
2155 HOTSPOT_JNI_SETOBJECTFIELD_RETURN();
2156JNI_END
2157
2158
2159#define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType \
2160 , EntryProbe, ReturnProbe) \
2161\
2162JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \
2163 JNIWrapper("Set" XSTR(Result) "Field"); \
2164\
2165 EntryProbe; \
2166\
2167 oop o = JNIHandles::resolve_non_null(obj); \
2168 Klass* k = o->klass(); \
2169 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \
2170 /* Keep JVMTI addition small and only check enabled flag here. */ \
2171 /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \
2172 /* and creates a ResetNoHandleMark. */ \
2173 if (JvmtiExport::should_post_field_modification()) { \
2174 jvalue field_value; \
2175 field_value.unionType = value; \
2176 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \
2177 } \
2178 if (SigType == 'Z') { value = ((jboolean)value) & 1; } \
2179 o->Fieldname##_field_put(offset, value); \
2180 ReturnProbe; \
2181JNI_END
2182
2183DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z
2184 , HOTSPOT_JNI_SETBOOLEANFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2185 HOTSPOT_JNI_SETBOOLEANFIELD_RETURN())
2186DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b
2187 , HOTSPOT_JNI_SETBYTEFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2188 HOTSPOT_JNI_SETBYTEFIELD_RETURN())
2189DEFINE_SETFIELD(jchar, char, Char, 'C', c
2190 , HOTSPOT_JNI_SETCHARFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2191 HOTSPOT_JNI_SETCHARFIELD_RETURN())
2192DEFINE_SETFIELD(jshort, short, Short, 'S', s
2193 , HOTSPOT_JNI_SETSHORTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2194 HOTSPOT_JNI_SETSHORTFIELD_RETURN())
2195DEFINE_SETFIELD(jint, int, Int, 'I', i
2196 , HOTSPOT_JNI_SETINTFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2197 HOTSPOT_JNI_SETINTFIELD_RETURN())
2198DEFINE_SETFIELD(jlong, long, Long, 'J', j
2199 , HOTSPOT_JNI_SETLONGFIELD_ENTRY(env, obj, (uintptr_t)fieldID, value),
2200 HOTSPOT_JNI_SETLONGFIELD_RETURN())
2201// Float and double probes don't return value because dtrace doesn't currently support it
2202DEFINE_SETFIELD(jfloat, float, Float, 'F', f
2203 , HOTSPOT_JNI_SETFLOATFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2204 HOTSPOT_JNI_SETFLOATFIELD_RETURN())
2205DEFINE_SETFIELD(jdouble, double, Double, 'D', d
2206 , HOTSPOT_JNI_SETDOUBLEFIELD_ENTRY(env, obj, (uintptr_t)fieldID),
2207 HOTSPOT_JNI_SETDOUBLEFIELD_RETURN())
2208
2209DT_RETURN_MARK_DECL(ToReflectedField, jobject
2210 , HOTSPOT_JNI_TOREFLECTEDFIELD_RETURN(_ret_ref));
2211
2212JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic))
2213 JNIWrapper("ToReflectedField");
2214 HOTSPOT_JNI_TOREFLECTEDFIELD_ENTRY(env, cls, (uintptr_t) fieldID, isStatic);
2215 jobject ret = NULL;
2216 DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret);
2217
2218 fieldDescriptor fd;
2219 bool found = false;
2220 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls));
2221
2222 assert(jfieldIDWorkaround::is_static_jfieldID(fieldID) == (isStatic != 0), "invalid fieldID");
2223
2224 if (isStatic) {
2225 // Static field. The fieldID a JNIid specifying the field holder and the offset within the Klass*.
2226 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
2227 assert(id->is_static_field_id(), "invalid static field id");
2228 found = id->find_local_field(&fd);
2229 } else {
2230 // Non-static field. The fieldID is really the offset of the field within the instanceOop.
2231 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID);
2232 found = InstanceKlass::cast(k)->find_field_from_offset(offset, false, &fd);
2233 }
2234 assert(found, "bad fieldID passed into jni_ToReflectedField");
2235 oop reflected = Reflection::new_field(&fd, CHECK_NULL);
2236 ret = JNIHandles::make_local(env, reflected);
2237 return ret;
2238JNI_END
2239
2240
2241//
2242// Accessing Static Fields
2243//
2244DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID
2245 , HOTSPOT_JNI_GETSTATICFIELDID_RETURN((uintptr_t)_ret_ref));
2246
2247JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz,
2248 const char *name, const char *sig))
2249 JNIWrapper("GetStaticFieldID");
2250 HOTSPOT_JNI_GETSTATICFIELDID_ENTRY(env, clazz, (char *) name, (char *) sig);
2251 jfieldID ret = NULL;
2252 DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret);
2253
2254 // The class should have been loaded (we have an instance of the class
2255 // passed in) so the field and signature should already be in the symbol
2256 // table. If they're not there, the field doesn't exist.
2257 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name));
2258 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig));
2259 if (fieldname == NULL || signame == NULL) {
2260 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
2261 }
2262 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
2263 // Make sure class is initialized before handing id's out to static fields
2264 k->initialize(CHECK_NULL);
2265
2266 fieldDescriptor fd;
2267 if (!k->is_instance_klass() ||
2268 !InstanceKlass::cast(k)->find_field(fieldname, signame, true, &fd)) {
2269 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name);
2270 }
2271
2272 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the Klass*
2273 JNIid* id = fd.field_holder()->jni_id_for(fd.offset());
2274 debug_only(id->set_is_static_field_id();)
2275
2276 debug_only(id->verify(fd.field_holder()));
2277
2278 ret = jfieldIDWorkaround::to_static_jfieldID(id);
2279 return ret;
2280JNI_END
2281
2282
2283JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID))
2284 JNIWrapper("GetStaticObjectField");
2285 HOTSPOT_JNI_GETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID);
2286#if INCLUDE_JNI_CHECK
2287 DEBUG_ONLY(Klass* param_k = jniCheck::validate_class(thread, clazz);)
2288#endif // INCLUDE_JNI_CHECK
2289 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
2290 assert(id->is_static_field_id(), "invalid static field id");
2291 // Keep JVMTI addition small and only check enabled flag here.
2292 // jni_GetField_probe() assumes that is okay to create handles.
2293 if (JvmtiExport::should_post_field_access()) {
2294 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true);
2295 }
2296 jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset()));
2297 HOTSPOT_JNI_GETSTATICOBJECTFIELD_RETURN(ret);
2298 return ret;
2299JNI_END
2300
2301
2302#define DEFINE_GETSTATICFIELD(Return,Fieldname,Result \
2303 , EntryProbe, ReturnProbe) \
2304\
2305 DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return \
2306 , ReturnProbe); \
2307\
2308JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \
2309 JNIWrapper("GetStatic" XSTR(Result) "Field"); \
2310 EntryProbe; \
2311 Return ret = 0;\
2312 DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \
2313 (const Return&)ret);\
2314 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
2315 assert(id->is_static_field_id(), "invalid static field id"); \
2316 /* Keep JVMTI addition small and only check enabled flag here. */ \
2317 /* jni_GetField_probe() assumes that is okay to create handles. */ \
2318 if (JvmtiExport::should_post_field_access()) { \
2319 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \
2320 } \
2321 ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \
2322 return ret;\
2323JNI_END
2324
2325DEFINE_GETSTATICFIELD(jboolean, bool, Boolean
2326 , HOTSPOT_JNI_GETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBOOLEANFIELD_RETURN(_ret_ref))
2327DEFINE_GETSTATICFIELD(jbyte, byte, Byte
2328 , HOTSPOT_JNI_GETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICBYTEFIELD_RETURN(_ret_ref) )
2329DEFINE_GETSTATICFIELD(jchar, char, Char
2330 , HOTSPOT_JNI_GETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICCHARFIELD_RETURN(_ret_ref) )
2331DEFINE_GETSTATICFIELD(jshort, short, Short
2332 , HOTSPOT_JNI_GETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICSHORTFIELD_RETURN(_ret_ref) )
2333DEFINE_GETSTATICFIELD(jint, int, Int
2334 , HOTSPOT_JNI_GETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICINTFIELD_RETURN(_ret_ref) )
2335DEFINE_GETSTATICFIELD(jlong, long, Long
2336 , HOTSPOT_JNI_GETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICLONGFIELD_RETURN(_ret_ref) )
2337// Float and double probes don't return value because dtrace doesn't currently support it
2338DEFINE_GETSTATICFIELD(jfloat, float, Float
2339 , HOTSPOT_JNI_GETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICFLOATFIELD_RETURN() )
2340DEFINE_GETSTATICFIELD(jdouble, double, Double
2341 , HOTSPOT_JNI_GETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID), HOTSPOT_JNI_GETSTATICDOUBLEFIELD_RETURN() )
2342
2343JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value))
2344 JNIWrapper("SetStaticObjectField");
2345 HOTSPOT_JNI_SETSTATICOBJECTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value);
2346 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID);
2347 assert(id->is_static_field_id(), "invalid static field id");
2348 // Keep JVMTI addition small and only check enabled flag here.
2349 // jni_SetField_probe() assumes that is okay to create handles.
2350 if (JvmtiExport::should_post_field_modification()) {
2351 jvalue field_value;
2352 field_value.l = value;
2353 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value);
2354 }
2355 id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value));
2356 HOTSPOT_JNI_SETSTATICOBJECTFIELD_RETURN();
2357JNI_END
2358
2359
2360
2361#define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType \
2362 , EntryProbe, ReturnProbe) \
2363\
2364JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \
2365 JNIWrapper("SetStatic" XSTR(Result) "Field"); \
2366 EntryProbe; \
2367\
2368 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \
2369 assert(id->is_static_field_id(), "invalid static field id"); \
2370 /* Keep JVMTI addition small and only check enabled flag here. */ \
2371 /* jni_SetField_probe() assumes that is okay to create handles. */ \
2372 if (JvmtiExport::should_post_field_modification()) { \
2373 jvalue field_value; \
2374 field_value.unionType = value; \
2375 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \
2376 } \
2377 if (SigType == 'Z') { value = ((jboolean)value) & 1; } \
2378 id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \
2379 ReturnProbe;\
2380JNI_END
2381
2382DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z
2383 , HOTSPOT_JNI_SETSTATICBOOLEANFIELD_ENTRY(env, clazz, (uintptr_t)fieldID, value),
2384 HOTSPOT_JNI_SETSTATICBOOLEANFIELD_RETURN())
2385DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b
2386 , HOTSPOT_JNI_SETSTATICBYTEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
2387 HOTSPOT_JNI_SETSTATICBYTEFIELD_RETURN())
2388DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c
2389 , HOTSPOT_JNI_SETSTATICCHARFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
2390 HOTSPOT_JNI_SETSTATICCHARFIELD_RETURN())
2391DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s
2392 , HOTSPOT_JNI_SETSTATICSHORTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
2393 HOTSPOT_JNI_SETSTATICSHORTFIELD_RETURN())
2394DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i
2395 , HOTSPOT_JNI_SETSTATICINTFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
2396 HOTSPOT_JNI_SETSTATICINTFIELD_RETURN())
2397DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j
2398 , HOTSPOT_JNI_SETSTATICLONGFIELD_ENTRY(env, clazz, (uintptr_t) fieldID, value),
2399 HOTSPOT_JNI_SETSTATICLONGFIELD_RETURN())
2400// Float and double probes don't return value because dtrace doesn't currently support it
2401DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f
2402 , HOTSPOT_JNI_SETSTATICFLOATFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),
2403 HOTSPOT_JNI_SETSTATICFLOATFIELD_RETURN())
2404DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d
2405 , HOTSPOT_JNI_SETSTATICDOUBLEFIELD_ENTRY(env, clazz, (uintptr_t) fieldID),
2406 HOTSPOT_JNI_SETSTATICDOUBLEFIELD_RETURN())
2407
2408//
2409// String Operations
2410//
2411
2412// Unicode Interface
2413
2414DT_RETURN_MARK_DECL(NewString, jstring
2415 , HOTSPOT_JNI_NEWSTRING_RETURN(_ret_ref));
2416
2417JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len))
2418 JNIWrapper("NewString");
2419 HOTSPOT_JNI_NEWSTRING_ENTRY(env, (uint16_t *) unicodeChars, len);
2420 jstring ret = NULL;
2421 DT_RETURN_MARK(NewString, jstring, (const jstring&)ret);
2422 oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL);
2423 ret = (jstring) JNIHandles::make_local(env, string);
2424 return ret;
2425JNI_END
2426
2427
2428JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string))
2429 JNIWrapper("GetStringLength");
2430 HOTSPOT_JNI_GETSTRINGLENGTH_ENTRY(env, string);
2431 jsize ret = 0;
2432 oop s = JNIHandles::resolve_non_null(string);
2433 ret = java_lang_String::length(s);
2434 HOTSPOT_JNI_GETSTRINGLENGTH_RETURN(ret);
2435 return ret;
2436JNI_END
2437
2438
2439JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars(
2440 JNIEnv *env, jstring string, jboolean *isCopy))
2441 JNIWrapper("GetStringChars");
2442 HOTSPOT_JNI_GETSTRINGCHARS_ENTRY(env, string, (uintptr_t *) isCopy);
2443 jchar* buf = NULL;
2444 oop s = JNIHandles::resolve_non_null(string);
2445 typeArrayOop s_value = java_lang_String::value(s);
2446 if (s_value != NULL) {
2447 int s_len = java_lang_String::length(s, s_value);
2448 bool is_latin1 = java_lang_String::is_latin1(s);
2449 buf = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
2450 /* JNI Specification states return NULL on OOM */
2451 if (buf != NULL) {
2452 if (s_len > 0) {
2453 if (!is_latin1) {
2454 ArrayAccess<>::arraycopy_to_native(s_value, (size_t) typeArrayOopDesc::element_offset<jchar>(0),
2455 buf, s_len);
2456 } else {
2457 for (int i = 0; i < s_len; i++) {
2458 buf[i] = ((jchar) s_value->byte_at(i)) & 0xff;
2459 }
2460 }
2461 }
2462 buf[s_len] = 0;
2463 //%note jni_5
2464 if (isCopy != NULL) {
2465 *isCopy = JNI_TRUE;
2466 }
2467 }
2468 }
2469 HOTSPOT_JNI_GETSTRINGCHARS_RETURN(buf);
2470 return buf;
2471JNI_END
2472
2473
2474JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars))
2475 JNIWrapper("ReleaseStringChars");
2476 HOTSPOT_JNI_RELEASESTRINGCHARS_ENTRY(env, str, (uint16_t *) chars);
2477 //%note jni_6
2478 if (chars != NULL) {
2479 // Since String objects are supposed to be immutable, don't copy any
2480 // new data back. A bad user will have to go after the char array.
2481 FreeHeap((void*) chars);
2482 }
2483 HOTSPOT_JNI_RELEASESTRINGCHARS_RETURN();
2484JNI_END
2485
2486
2487// UTF Interface
2488
2489DT_RETURN_MARK_DECL(NewStringUTF, jstring
2490 , HOTSPOT_JNI_NEWSTRINGUTF_RETURN(_ret_ref));
2491
2492JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes))
2493 JNIWrapper("NewStringUTF");
2494 HOTSPOT_JNI_NEWSTRINGUTF_ENTRY(env, (char *) bytes);
2495 jstring ret;
2496 DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret);
2497
2498 oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL);
2499 ret = (jstring) JNIHandles::make_local(env, result);
2500 return ret;
2501JNI_END
2502
2503
2504JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string))
2505 JNIWrapper("GetStringUTFLength");
2506 HOTSPOT_JNI_GETSTRINGUTFLENGTH_ENTRY(env, string);
2507 oop java_string = JNIHandles::resolve_non_null(string);
2508 jsize ret = java_lang_String::utf8_length(java_string);
2509 HOTSPOT_JNI_GETSTRINGUTFLENGTH_RETURN(ret);
2510 return ret;
2511JNI_END
2512
2513
2514JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy))
2515 JNIWrapper("GetStringUTFChars");
2516 HOTSPOT_JNI_GETSTRINGUTFCHARS_ENTRY(env, string, (uintptr_t *) isCopy);
2517 char* result = NULL;
2518 oop java_string = JNIHandles::resolve_non_null(string);
2519 typeArrayOop s_value = java_lang_String::value(java_string);
2520 if (s_value != NULL) {
2521 size_t length = java_lang_String::utf8_length(java_string, s_value);
2522 /* JNI Specification states return NULL on OOM */
2523 result = AllocateHeap(length + 1, mtInternal, 0, AllocFailStrategy::RETURN_NULL);
2524 if (result != NULL) {
2525 java_lang_String::as_utf8_string(java_string, s_value, result, (int) length + 1);
2526 if (isCopy != NULL) {
2527 *isCopy = JNI_TRUE;
2528 }
2529 }
2530 }
2531 HOTSPOT_JNI_GETSTRINGUTFCHARS_RETURN(result);
2532 return result;
2533JNI_END
2534
2535
2536JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars))
2537 JNIWrapper("ReleaseStringUTFChars");
2538 HOTSPOT_JNI_RELEASESTRINGUTFCHARS_ENTRY(env, str, (char *) chars);
2539 if (chars != NULL) {
2540 FreeHeap((char*) chars);
2541 }
2542HOTSPOT_JNI_RELEASESTRINGUTFCHARS_RETURN();
2543JNI_END
2544
2545
2546JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array))
2547 JNIWrapper("GetArrayLength");
2548 HOTSPOT_JNI_GETARRAYLENGTH_ENTRY(env, array);
2549 arrayOop a = arrayOop(JNIHandles::resolve_non_null(array));
2550 assert(a->is_array(), "must be array");
2551 jsize ret = a->length();
2552 HOTSPOT_JNI_GETARRAYLENGTH_RETURN(ret);
2553 return ret;
2554JNI_END
2555
2556
2557//
2558// Object Array Operations
2559//
2560
2561DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray
2562 , HOTSPOT_JNI_NEWOBJECTARRAY_RETURN(_ret_ref));
2563
2564JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement))
2565 JNIWrapper("NewObjectArray");
2566 HOTSPOT_JNI_NEWOBJECTARRAY_ENTRY(env, length, elementClass, initialElement);
2567 jobjectArray ret = NULL;
2568 DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret);
2569 Klass* ek = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(elementClass));
2570 Klass* ak = ek->array_klass(CHECK_NULL);
2571 ObjArrayKlass::cast(ak)->initialize(CHECK_NULL);
2572 objArrayOop result = ObjArrayKlass::cast(ak)->allocate(length, CHECK_NULL);
2573 oop initial_value = JNIHandles::resolve(initialElement);
2574 if (initial_value != NULL) { // array already initialized with NULL
2575 for (int index = 0; index < length; index++) {
2576 result->obj_at_put(index, initial_value);
2577 }
2578 }
2579 ret = (jobjectArray) JNIHandles::make_local(env, result);
2580 return ret;
2581JNI_END
2582
2583DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject
2584 , HOTSPOT_JNI_GETOBJECTARRAYELEMENT_RETURN(_ret_ref));
2585
2586JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index))
2587 JNIWrapper("GetObjectArrayElement");
2588 HOTSPOT_JNI_GETOBJECTARRAYELEMENT_ENTRY(env, array, index);
2589 jobject ret = NULL;
2590 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret);
2591 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2592 if (a->is_within_bounds(index)) {
2593 ret = JNIHandles::make_local(env, a->obj_at(index));
2594 return ret;
2595 } else {
2596 ResourceMark rm(THREAD);
2597 stringStream ss;
2598 ss.print("Index %d out of bounds for length %d", index, a->length());
2599 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2600 }
2601JNI_END
2602
2603DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement
2604 , HOTSPOT_JNI_SETOBJECTARRAYELEMENT_RETURN());
2605
2606JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value))
2607 JNIWrapper("SetObjectArrayElement");
2608 HOTSPOT_JNI_SETOBJECTARRAYELEMENT_ENTRY(env, array, index, value);
2609 DT_VOID_RETURN_MARK(SetObjectArrayElement);
2610
2611 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array));
2612 oop v = JNIHandles::resolve(value);
2613 if (a->is_within_bounds(index)) {
2614 if (v == NULL || v->is_a(ObjArrayKlass::cast(a->klass())->element_klass())) {
2615 a->obj_at_put(index, v);
2616 } else {
2617 ResourceMark rm(THREAD);
2618 stringStream ss;
2619 Klass *bottom_kl = ObjArrayKlass::cast(a->klass())->bottom_klass();
2620 ss.print("type mismatch: can not store %s to %s[%d]",
2621 v->klass()->external_name(),
2622 bottom_kl->is_typeArray_klass() ? type2name_tab[ArrayKlass::cast(bottom_kl)->element_type()] : bottom_kl->external_name(),
2623 index);
2624 for (int dims = ArrayKlass::cast(a->klass())->dimension(); dims > 1; --dims) {
2625 ss.print("[]");
2626 }
2627 THROW_MSG(vmSymbols::java_lang_ArrayStoreException(), ss.as_string());
2628 }
2629 } else {
2630 ResourceMark rm(THREAD);
2631 stringStream ss;
2632 ss.print("Index %d out of bounds for length %d", index, a->length());
2633 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2634 }
2635JNI_END
2636
2637
2638
2639#define DEFINE_NEWSCALARARRAY(Return,Allocator,Result \
2640 ,EntryProbe,ReturnProbe) \
2641\
2642 DT_RETURN_MARK_DECL(New##Result##Array, Return \
2643 , ReturnProbe); \
2644\
2645JNI_ENTRY(Return, \
2646 jni_New##Result##Array(JNIEnv *env, jsize len)) \
2647 JNIWrapper("New" XSTR(Result) "Array"); \
2648 EntryProbe; \
2649 Return ret = NULL;\
2650 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\
2651\
2652 oop obj= oopFactory::Allocator(len, CHECK_0); \
2653 ret = (Return) JNIHandles::make_local(env, obj); \
2654 return ret;\
2655JNI_END
2656
2657DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean,
2658 HOTSPOT_JNI_NEWBOOLEANARRAY_ENTRY(env, len),
2659 HOTSPOT_JNI_NEWBOOLEANARRAY_RETURN(_ret_ref))
2660DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte,
2661 HOTSPOT_JNI_NEWBYTEARRAY_ENTRY(env, len),
2662 HOTSPOT_JNI_NEWBYTEARRAY_RETURN(_ret_ref))
2663DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short,
2664 HOTSPOT_JNI_NEWSHORTARRAY_ENTRY(env, len),
2665 HOTSPOT_JNI_NEWSHORTARRAY_RETURN(_ret_ref))
2666DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char,
2667 HOTSPOT_JNI_NEWCHARARRAY_ENTRY(env, len),
2668 HOTSPOT_JNI_NEWCHARARRAY_RETURN(_ret_ref))
2669DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int,
2670 HOTSPOT_JNI_NEWINTARRAY_ENTRY(env, len),
2671 HOTSPOT_JNI_NEWINTARRAY_RETURN(_ret_ref))
2672DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long,
2673 HOTSPOT_JNI_NEWLONGARRAY_ENTRY(env, len),
2674 HOTSPOT_JNI_NEWLONGARRAY_RETURN(_ret_ref))
2675DEFINE_NEWSCALARARRAY(jfloatArray, new_floatArray, Float,
2676 HOTSPOT_JNI_NEWFLOATARRAY_ENTRY(env, len),
2677 HOTSPOT_JNI_NEWFLOATARRAY_RETURN(_ret_ref))
2678DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double,
2679 HOTSPOT_JNI_NEWDOUBLEARRAY_ENTRY(env, len),
2680 HOTSPOT_JNI_NEWDOUBLEARRAY_RETURN(_ret_ref))
2681
2682// Return an address which will fault if the caller writes to it.
2683
2684static char* get_bad_address() {
2685 static char* bad_address = NULL;
2686 if (bad_address == NULL) {
2687 size_t size = os::vm_allocation_granularity();
2688 bad_address = os::reserve_memory(size);
2689 if (bad_address != NULL) {
2690 os::protect_memory(bad_address, size, os::MEM_PROT_READ,
2691 /*is_committed*/false);
2692 MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal);
2693 }
2694 }
2695 return bad_address;
2696}
2697
2698
2699
2700#define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag \
2701 , EntryProbe, ReturnProbe) \
2702\
2703JNI_QUICK_ENTRY(ElementType*, \
2704 jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \
2705 JNIWrapper("Get" XSTR(Result) "ArrayElements"); \
2706 EntryProbe; \
2707 /* allocate an chunk of memory in c land */ \
2708 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
2709 ElementType* result; \
2710 int len = a->length(); \
2711 if (len == 0) { \
2712 if (isCopy != NULL) { \
2713 *isCopy = JNI_FALSE; \
2714 } \
2715 /* Empty array: legal but useless, can't return NULL. \
2716 * Return a pointer to something useless. \
2717 * Avoid asserts in typeArrayOop. */ \
2718 result = (ElementType*)get_bad_address(); \
2719 } else { \
2720 /* JNI Specification states return NULL on OOM */ \
2721 result = NEW_C_HEAP_ARRAY_RETURN_NULL(ElementType, len, mtInternal); \
2722 if (result != NULL) { \
2723 /* copy the array to the c chunk */ \
2724 ArrayAccess<>::arraycopy_to_native(a, typeArrayOopDesc::element_offset<ElementType>(0), \
2725 result, len); \
2726 if (isCopy) { \
2727 *isCopy = JNI_TRUE; \
2728 } \
2729 } \
2730 } \
2731 ReturnProbe; \
2732 return result; \
2733JNI_END
2734
2735DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool
2736 , HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2737 HOTSPOT_JNI_GETBOOLEANARRAYELEMENTS_RETURN((uintptr_t*)result))
2738DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte
2739 , HOTSPOT_JNI_GETBYTEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2740 HOTSPOT_JNI_GETBYTEARRAYELEMENTS_RETURN((char*)result))
2741DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short
2742 , HOTSPOT_JNI_GETSHORTARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),
2743 HOTSPOT_JNI_GETSHORTARRAYELEMENTS_RETURN((uint16_t*)result))
2744DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char
2745 , HOTSPOT_JNI_GETCHARARRAYELEMENTS_ENTRY(env, (uint16_t*) array, (uintptr_t *) isCopy),
2746 HOTSPOT_JNI_GETCHARARRAYELEMENTS_RETURN(result))
2747DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int
2748 , HOTSPOT_JNI_GETINTARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2749 HOTSPOT_JNI_GETINTARRAYELEMENTS_RETURN((uint32_t*)result))
2750DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long
2751 , HOTSPOT_JNI_GETLONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2752 HOTSPOT_JNI_GETLONGARRAYELEMENTS_RETURN(((uintptr_t*)result)))
2753// Float and double probes don't return value because dtrace doesn't currently support it
2754DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float
2755 , HOTSPOT_JNI_GETFLOATARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2756 HOTSPOT_JNI_GETFLOATARRAYELEMENTS_RETURN(result))
2757DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double
2758 , HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) isCopy),
2759 HOTSPOT_JNI_GETDOUBLEARRAYELEMENTS_RETURN(result))
2760
2761
2762#define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag \
2763 , EntryProbe, ReturnProbe);\
2764\
2765JNI_QUICK_ENTRY(void, \
2766 jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \
2767 ElementType *buf, jint mode)) \
2768 JNIWrapper("Release" XSTR(Result) "ArrayElements"); \
2769 EntryProbe; \
2770 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
2771 int len = a->length(); \
2772 if (len != 0) { /* Empty array: nothing to free or copy. */ \
2773 if ((mode == 0) || (mode == JNI_COMMIT)) { \
2774 ArrayAccess<>::arraycopy_from_native(buf, a, typeArrayOopDesc::element_offset<ElementType>(0), len); \
2775 } \
2776 if ((mode == 0) || (mode == JNI_ABORT)) { \
2777 FreeHeap(buf); \
2778 } \
2779 } \
2780 ReturnProbe; \
2781JNI_END
2782
2783DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool
2784 , HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),
2785 HOTSPOT_JNI_RELEASEBOOLEANARRAYELEMENTS_RETURN())
2786DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte
2787 , HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_ENTRY(env, array, (char *) buf, mode),
2788 HOTSPOT_JNI_RELEASEBYTEARRAYELEMENTS_RETURN())
2789DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short
2790 , HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),
2791 HOTSPOT_JNI_RELEASESHORTARRAYELEMENTS_RETURN())
2792DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char
2793 , HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_ENTRY(env, array, (uint16_t *) buf, mode),
2794 HOTSPOT_JNI_RELEASECHARARRAYELEMENTS_RETURN())
2795DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int
2796 , HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_ENTRY(env, array, (uint32_t *) buf, mode),
2797 HOTSPOT_JNI_RELEASEINTARRAYELEMENTS_RETURN())
2798DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long
2799 , HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_ENTRY(env, array, (uintptr_t *) buf, mode),
2800 HOTSPOT_JNI_RELEASELONGARRAYELEMENTS_RETURN())
2801DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float
2802 , HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_ENTRY(env, array, (float *) buf, mode),
2803 HOTSPOT_JNI_RELEASEFLOATARRAYELEMENTS_RETURN())
2804DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double
2805 , HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_ENTRY(env, array, (double *) buf, mode),
2806 HOTSPOT_JNI_RELEASEDOUBLEARRAYELEMENTS_RETURN())
2807
2808static void check_bounds(jsize start, jsize copy_len, jsize array_len, TRAPS) {
2809 ResourceMark rm(THREAD);
2810 if (copy_len < 0) {
2811 stringStream ss;
2812 ss.print("Length %d is negative", copy_len);
2813 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2814 } else if (start < 0 || (start > array_len - copy_len)) {
2815 stringStream ss;
2816 ss.print("Array region %d.." INT64_FORMAT " out of bounds for length %d",
2817 start, (int64_t)start+(int64_t)copy_len, array_len);
2818 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), ss.as_string());
2819 }
2820}
2821
2822#define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \
2823 , EntryProbe, ReturnProbe); \
2824 DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion \
2825 , ReturnProbe); \
2826\
2827JNI_ENTRY(void, \
2828jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
2829 jsize len, ElementType *buf)) \
2830 JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \
2831 EntryProbe; \
2832 DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \
2833 typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \
2834 check_bounds(start, len, src->length(), CHECK); \
2835 if (len > 0) { \
2836 ArrayAccess<>::arraycopy_to_native(src, typeArrayOopDesc::element_offset<ElementType>(start), buf, len); \
2837 } \
2838JNI_END
2839
2840DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool
2841 , HOTSPOT_JNI_GETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
2842 HOTSPOT_JNI_GETBOOLEANARRAYREGION_RETURN());
2843DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte
2844 , HOTSPOT_JNI_GETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),
2845 HOTSPOT_JNI_GETBYTEARRAYREGION_RETURN());
2846DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short
2847 , HOTSPOT_JNI_GETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
2848 HOTSPOT_JNI_GETSHORTARRAYREGION_RETURN());
2849DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char
2850 , HOTSPOT_JNI_GETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t*) buf),
2851 HOTSPOT_JNI_GETCHARARRAYREGION_RETURN());
2852DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int
2853 , HOTSPOT_JNI_GETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t*) buf),
2854 HOTSPOT_JNI_GETINTARRAYREGION_RETURN());
2855DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long
2856 , HOTSPOT_JNI_GETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
2857 HOTSPOT_JNI_GETLONGARRAYREGION_RETURN());
2858DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float
2859 , HOTSPOT_JNI_GETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),
2860 HOTSPOT_JNI_GETFLOATARRAYREGION_RETURN());
2861DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double
2862 , HOTSPOT_JNI_GETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),
2863 HOTSPOT_JNI_GETDOUBLEARRAYREGION_RETURN());
2864
2865
2866#define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag \
2867 , EntryProbe, ReturnProbe); \
2868 DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion \
2869 ,ReturnProbe); \
2870\
2871JNI_ENTRY(void, \
2872jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \
2873 jsize len, const ElementType *buf)) \
2874 JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \
2875 EntryProbe; \
2876 DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \
2877 typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \
2878 check_bounds(start, len, dst->length(), CHECK); \
2879 if (len > 0) { \
2880 ArrayAccess<>::arraycopy_from_native(buf, dst, typeArrayOopDesc::element_offset<ElementType>(start), len); \
2881 } \
2882JNI_END
2883
2884DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool
2885 , HOTSPOT_JNI_SETBOOLEANARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *)buf),
2886 HOTSPOT_JNI_SETBOOLEANARRAYREGION_RETURN())
2887DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte
2888 , HOTSPOT_JNI_SETBYTEARRAYREGION_ENTRY(env, array, start, len, (char *) buf),
2889 HOTSPOT_JNI_SETBYTEARRAYREGION_RETURN())
2890DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short
2891 , HOTSPOT_JNI_SETSHORTARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
2892 HOTSPOT_JNI_SETSHORTARRAYREGION_RETURN())
2893DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char
2894 , HOTSPOT_JNI_SETCHARARRAYREGION_ENTRY(env, array, start, len, (uint16_t *) buf),
2895 HOTSPOT_JNI_SETCHARARRAYREGION_RETURN())
2896DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int
2897 , HOTSPOT_JNI_SETINTARRAYREGION_ENTRY(env, array, start, len, (uint32_t *) buf),
2898 HOTSPOT_JNI_SETINTARRAYREGION_RETURN())
2899DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long
2900 , HOTSPOT_JNI_SETLONGARRAYREGION_ENTRY(env, array, start, len, (uintptr_t *) buf),
2901 HOTSPOT_JNI_SETLONGARRAYREGION_RETURN())
2902DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float
2903 , HOTSPOT_JNI_SETFLOATARRAYREGION_ENTRY(env, array, start, len, (float *) buf),
2904 HOTSPOT_JNI_SETFLOATARRAYREGION_RETURN())
2905DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double
2906 , HOTSPOT_JNI_SETDOUBLEARRAYREGION_ENTRY(env, array, start, len, (double *) buf),
2907 HOTSPOT_JNI_SETDOUBLEARRAYREGION_RETURN())
2908
2909
2910//
2911// Interception of natives
2912//
2913
2914// The RegisterNatives call being attempted tried to register with a method that
2915// is not native. Ask JVM TI what prefixes have been specified. Then check
2916// to see if the native method is now wrapped with the prefixes. See the
2917// SetNativeMethodPrefix(es) functions in the JVM TI Spec for details.
2918static Method* find_prefixed_native(Klass* k, Symbol* name, Symbol* signature, TRAPS) {
2919#if INCLUDE_JVMTI
2920 ResourceMark rm(THREAD);
2921 Method* method;
2922 int name_len = name->utf8_length();
2923 char* name_str = name->as_utf8();
2924 int prefix_count;
2925 char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count);
2926 for (int i = 0; i < prefix_count; i++) {
2927 char* prefix = prefixes[i];
2928 int prefix_len = (int)strlen(prefix);
2929
2930 // try adding this prefix to the method name and see if it matches another method name
2931 int trial_len = name_len + prefix_len;
2932 char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1);
2933 strcpy(trial_name_str, prefix);
2934 strcat(trial_name_str, name_str);
2935 TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len);
2936 if (trial_name == NULL) {
2937 continue; // no such symbol, so this prefix wasn't used, try the next prefix
2938 }
2939 method = k->lookup_method(trial_name, signature);
2940 if (method == NULL) {
2941 continue; // signature doesn't match, try the next prefix
2942 }
2943 if (method->is_native()) {
2944 method->set_is_prefixed_native();
2945 return method; // wahoo, we found a prefixed version of the method, return it
2946 }
2947 // found as non-native, so prefix is good, add it, probably just need more prefixes
2948 name_len = trial_len;
2949 name_str = trial_name_str;
2950 }
2951#endif // INCLUDE_JVMTI
2952 return NULL; // not found
2953}
2954
2955static bool register_native(Klass* k, Symbol* name, Symbol* signature, address entry, TRAPS) {
2956 Method* method = k->lookup_method(name, signature);
2957 if (method == NULL) {
2958 ResourceMark rm;
2959 stringStream st;
2960 st.print("Method '");
2961 Method::print_external_name(&st, k, name, signature);
2962 st.print("' name or signature does not match");
2963 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
2964 }
2965 if (!method->is_native()) {
2966 // trying to register to a non-native method, see if a JVM TI agent has added prefix(es)
2967 method = find_prefixed_native(k, name, signature, THREAD);
2968 if (method == NULL) {
2969 ResourceMark rm;
2970 stringStream st;
2971 st.print("Method '");
2972 Method::print_external_name(&st, k, name, signature);
2973 st.print("' is not declared as native");
2974 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false);
2975 }
2976 }
2977
2978 if (entry != NULL) {
2979 method->set_native_function(entry,
2980 Method::native_bind_event_is_interesting);
2981 } else {
2982 method->clear_native_function();
2983 }
2984 if (PrintJNIResolving) {
2985 ResourceMark rm(THREAD);
2986 tty->print_cr("[Registering JNI native method %s.%s]",
2987 method->method_holder()->external_name(),
2988 method->name()->as_C_string());
2989 }
2990 return true;
2991}
2992
2993DT_RETURN_MARK_DECL(RegisterNatives, jint
2994 , HOTSPOT_JNI_REGISTERNATIVES_RETURN(_ret_ref));
2995
2996JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz,
2997 const JNINativeMethod *methods,
2998 jint nMethods))
2999 JNIWrapper("RegisterNatives");
3000 HOTSPOT_JNI_REGISTERNATIVES_ENTRY(env, clazz, (void *) methods, nMethods);
3001 jint ret = 0;
3002 DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret);
3003
3004 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
3005
3006 for (int index = 0; index < nMethods; index++) {
3007 const char* meth_name = methods[index].name;
3008 const char* meth_sig = methods[index].signature;
3009 int meth_name_len = (int)strlen(meth_name);
3010
3011 // The class should have been loaded (we have an instance of the class
3012 // passed in) so the method and signature should already be in the symbol
3013 // table. If they're not there, the method doesn't exist.
3014 TempNewSymbol name = SymbolTable::probe(meth_name, meth_name_len);
3015 TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig));
3016
3017 if (name == NULL || signature == NULL) {
3018 ResourceMark rm;
3019 stringStream st;
3020 st.print("Method %s.%s%s not found", k->external_name(), meth_name, meth_sig);
3021 // Must return negative value on failure
3022 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1);
3023 }
3024
3025 bool res = register_native(k, name, signature,
3026 (address) methods[index].fnPtr, THREAD);
3027 if (!res) {
3028 ret = -1;
3029 break;
3030 }
3031 }
3032 return ret;
3033JNI_END
3034
3035
3036JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz))
3037 JNIWrapper("UnregisterNatives");
3038 HOTSPOT_JNI_UNREGISTERNATIVES_ENTRY(env, clazz);
3039 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz));
3040 //%note jni_2
3041 if (k->is_instance_klass()) {
3042 for (int index = 0; index < InstanceKlass::cast(k)->methods()->length(); index++) {
3043 Method* m = InstanceKlass::cast(k)->methods()->at(index);
3044 if (m->is_native()) {
3045 m->clear_native_function();
3046 m->set_signature_handler(NULL);
3047 }
3048 }
3049 }
3050 HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(0);
3051 return 0;
3052JNI_END
3053
3054//
3055// Monitor functions
3056//
3057
3058DT_RETURN_MARK_DECL(MonitorEnter, jint
3059 , HOTSPOT_JNI_MONITORENTER_RETURN(_ret_ref));
3060
3061JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
3062 HOTSPOT_JNI_MONITORENTER_ENTRY(env, jobj);
3063 jint ret = JNI_ERR;
3064 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret);
3065
3066 // If the object is null, we can't do anything with it
3067 if (jobj == NULL) {
3068 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
3069 }
3070
3071 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
3072 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
3073 ret = JNI_OK;
3074 return ret;
3075JNI_END
3076
3077DT_RETURN_MARK_DECL(MonitorExit, jint
3078 , HOTSPOT_JNI_MONITOREXIT_RETURN(_ret_ref));
3079
3080JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj))
3081 HOTSPOT_JNI_MONITOREXIT_ENTRY(env, jobj);
3082 jint ret = JNI_ERR;
3083 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret);
3084
3085 // Don't do anything with a null object
3086 if (jobj == NULL) {
3087 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR);
3088 }
3089
3090 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
3091 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR));
3092
3093 ret = JNI_OK;
3094 return ret;
3095JNI_END
3096
3097//
3098// Extensions
3099//
3100
3101DT_VOID_RETURN_MARK_DECL(GetStringRegion
3102 , HOTSPOT_JNI_GETSTRINGREGION_RETURN());
3103
3104JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf))
3105 JNIWrapper("GetStringRegion");
3106 HOTSPOT_JNI_GETSTRINGREGION_ENTRY(env, string, start, len, buf);
3107 DT_VOID_RETURN_MARK(GetStringRegion);
3108 oop s = JNIHandles::resolve_non_null(string);
3109 typeArrayOop s_value = java_lang_String::value(s);
3110 int s_len = java_lang_String::length(s, s_value);
3111 if (start < 0 || len < 0 || start > s_len - len) {
3112 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
3113 } else {
3114 if (len > 0) {
3115 bool is_latin1 = java_lang_String::is_latin1(s);
3116 if (!is_latin1) {
3117 ArrayAccess<>::arraycopy_to_native(s_value, typeArrayOopDesc::element_offset<jchar>(start),
3118 buf, len);
3119 } else {
3120 for (int i = 0; i < len; i++) {
3121 buf[i] = ((jchar) s_value->byte_at(i + start)) & 0xff;
3122 }
3123 }
3124 }
3125 }
3126JNI_END
3127
3128DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion
3129 , HOTSPOT_JNI_GETSTRINGUTFREGION_RETURN());
3130
3131JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf))
3132 JNIWrapper("GetStringUTFRegion");
3133 HOTSPOT_JNI_GETSTRINGUTFREGION_ENTRY(env, string, start, len, buf);
3134 DT_VOID_RETURN_MARK(GetStringUTFRegion);
3135 oop s = JNIHandles::resolve_non_null(string);
3136 typeArrayOop s_value = java_lang_String::value(s);
3137 int s_len = java_lang_String::length(s, s_value);
3138 if (start < 0 || len < 0 || start > s_len - len) {
3139 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException());
3140 } else {
3141 //%note jni_7
3142 if (len > 0) {
3143 // Assume the buffer is large enough as the JNI spec. does not require user error checking
3144 java_lang_String::as_utf8_string(s, s_value, start, len, buf, INT_MAX);
3145 // as_utf8_string null-terminates the result string
3146 } else {
3147 // JDK null-terminates the buffer even in len is zero
3148 if (buf != NULL) {
3149 buf[0] = 0;
3150 }
3151 }
3152 }
3153JNI_END
3154
3155static oop lock_gc_or_pin_object(JavaThread* thread, jobject obj) {
3156 if (Universe::heap()->supports_object_pinning()) {
3157 const oop o = JNIHandles::resolve_non_null(obj);
3158 return Universe::heap()->pin_object(thread, o);
3159 } else {
3160 GCLocker::lock_critical(thread);
3161 return JNIHandles::resolve_non_null(obj);
3162 }
3163}
3164
3165static void unlock_gc_or_unpin_object(JavaThread* thread, jobject obj) {
3166 if (Universe::heap()->supports_object_pinning()) {
3167 const oop o = JNIHandles::resolve_non_null(obj);
3168 return Universe::heap()->unpin_object(thread, o);
3169 } else {
3170 GCLocker::unlock_critical(thread);
3171 }
3172}
3173
3174JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy))
3175 JNIWrapper("GetPrimitiveArrayCritical");
3176 HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(env, array, (uintptr_t *) isCopy);
3177 if (isCopy != NULL) {
3178 *isCopy = JNI_FALSE;
3179 }
3180 oop a = lock_gc_or_pin_object(thread, array);
3181 assert(a->is_array(), "just checking");
3182 BasicType type;
3183 if (a->is_objArray()) {
3184 type = T_OBJECT;
3185 } else {
3186 type = TypeArrayKlass::cast(a->klass())->element_type();
3187 }
3188 void* ret = arrayOop(a)->base(type);
3189 HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_RETURN(ret);
3190 return ret;
3191JNI_END
3192
3193
3194JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode))
3195 JNIWrapper("ReleasePrimitiveArrayCritical");
3196 HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(env, array, carray, mode);
3197 unlock_gc_or_unpin_object(thread, array);
3198HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN();
3199JNI_END
3200
3201
3202JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy))
3203 JNIWrapper("GetStringCritical");
3204 HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy);
3205 oop s = lock_gc_or_pin_object(thread, string);
3206 typeArrayOop s_value = java_lang_String::value(s);
3207 bool is_latin1 = java_lang_String::is_latin1(s);
3208 if (isCopy != NULL) {
3209 *isCopy = is_latin1 ? JNI_TRUE : JNI_FALSE;
3210 }
3211 jchar* ret;
3212 if (!is_latin1) {
3213 ret = (jchar*) s_value->base(T_CHAR);
3214 } else {
3215 // Inflate latin1 encoded string to UTF16
3216 int s_len = java_lang_String::length(s, s_value);
3217 ret = NEW_C_HEAP_ARRAY_RETURN_NULL(jchar, s_len + 1, mtInternal); // add one for zero termination
3218 /* JNI Specification states return NULL on OOM */
3219 if (ret != NULL) {
3220 for (int i = 0; i < s_len; i++) {
3221 ret[i] = ((jchar) s_value->byte_at(i)) & 0xff;
3222 }
3223 ret[s_len] = 0;
3224 }
3225 }
3226 HOTSPOT_JNI_GETSTRINGCRITICAL_RETURN((uint16_t *) ret);
3227 return ret;
3228JNI_END
3229
3230
3231JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars))
3232 JNIWrapper("ReleaseStringCritical");
3233 HOTSPOT_JNI_RELEASESTRINGCRITICAL_ENTRY(env, str, (uint16_t *) chars);
3234 // The str and chars arguments are ignored for UTF16 strings
3235 oop s = JNIHandles::resolve_non_null(str);
3236 bool is_latin1 = java_lang_String::is_latin1(s);
3237 if (is_latin1) {
3238 // For latin1 string, free jchar array allocated by earlier call to GetStringCritical.
3239 // This assumes that ReleaseStringCritical bookends GetStringCritical.
3240 FREE_C_HEAP_ARRAY(jchar, chars);
3241 }
3242 unlock_gc_or_unpin_object(thread, str);
3243HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
3244JNI_END
3245
3246
3247JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref))
3248 JNIWrapper("jni_NewWeakGlobalRef");
3249 HOTSPOT_JNI_NEWWEAKGLOBALREF_ENTRY(env, ref);
3250 Handle ref_handle(thread, JNIHandles::resolve(ref));
3251 jweak ret = JNIHandles::make_weak_global(ref_handle);
3252 HOTSPOT_JNI_NEWWEAKGLOBALREF_RETURN(ret);
3253 return ret;
3254JNI_END
3255
3256// Must be JNI_ENTRY (with HandleMark)
3257JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref))
3258 JNIWrapper("jni_DeleteWeakGlobalRef");
3259 HOTSPOT_JNI_DELETEWEAKGLOBALREF_ENTRY(env, ref);
3260 JNIHandles::destroy_weak_global(ref);
3261 HOTSPOT_JNI_DELETEWEAKGLOBALREF_RETURN();
3262JNI_END
3263
3264
3265JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env))
3266 JNIWrapper("jni_ExceptionCheck");
3267 HOTSPOT_JNI_EXCEPTIONCHECK_ENTRY(env);
3268 jni_check_async_exceptions(thread);
3269 jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE;
3270 HOTSPOT_JNI_EXCEPTIONCHECK_RETURN(ret);
3271 return ret;
3272JNI_END
3273
3274
3275// Initialization state for three routines below relating to
3276// java.nio.DirectBuffers
3277static int directBufferSupportInitializeStarted = 0;
3278static volatile int directBufferSupportInitializeEnded = 0;
3279static volatile int directBufferSupportInitializeFailed = 0;
3280static jclass bufferClass = NULL;
3281static jclass directBufferClass = NULL;
3282static jclass directByteBufferClass = NULL;
3283static jmethodID directByteBufferConstructor = NULL;
3284static jfieldID directBufferAddressField = NULL;
3285static jfieldID bufferCapacityField = NULL;
3286
3287static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) {
3288 Handle loader; // null (bootstrap) loader
3289 Handle protection_domain; // null protection domain
3290
3291 TempNewSymbol sym = SymbolTable::new_symbol(name);
3292 jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL);
3293
3294 if (log_is_enabled(Debug, class, resolve) && result != NULL) {
3295 trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result)));
3296 }
3297 return result;
3298}
3299
3300// These lookups are done with the NULL (bootstrap) ClassLoader to
3301// circumvent any security checks that would be done by jni_FindClass.
3302JNI_ENTRY(bool, lookupDirectBufferClasses(JNIEnv* env))
3303{
3304 if ((bufferClass = lookupOne(env, "java/nio/Buffer", thread)) == NULL) { return false; }
3305 if ((directBufferClass = lookupOne(env, "sun/nio/ch/DirectBuffer", thread)) == NULL) { return false; }
3306 if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer", thread)) == NULL) { return false; }
3307 return true;
3308}
3309JNI_END
3310
3311
3312static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) {
3313 if (directBufferSupportInitializeFailed) {
3314 return false;
3315 }
3316
3317 if (Atomic::cmpxchg(1, &directBufferSupportInitializeStarted, 0) == 0) {
3318 if (!lookupDirectBufferClasses(env)) {
3319 directBufferSupportInitializeFailed = 1;
3320 return false;
3321 }
3322
3323 // Make global references for these
3324 bufferClass = (jclass) env->NewGlobalRef(bufferClass);
3325 directBufferClass = (jclass) env->NewGlobalRef(directBufferClass);
3326 directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass);
3327
3328 // Get needed field and method IDs
3329 directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V");
3330 if (env->ExceptionCheck()) {
3331 env->ExceptionClear();
3332 directBufferSupportInitializeFailed = 1;
3333 return false;
3334 }
3335 directBufferAddressField = env->GetFieldID(bufferClass, "address", "J");
3336 if (env->ExceptionCheck()) {
3337 env->ExceptionClear();
3338 directBufferSupportInitializeFailed = 1;
3339 return false;
3340 }
3341 bufferCapacityField = env->GetFieldID(bufferClass, "capacity", "I");
3342 if (env->ExceptionCheck()) {
3343 env->ExceptionClear();
3344 directBufferSupportInitializeFailed = 1;
3345 return false;
3346 }
3347
3348 if ((directByteBufferConstructor == NULL) ||
3349 (directBufferAddressField == NULL) ||
3350 (bufferCapacityField == NULL)) {
3351 directBufferSupportInitializeFailed = 1;
3352 return false;
3353 }
3354
3355 directBufferSupportInitializeEnded = 1;
3356 } else {
3357 while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) {
3358 os::naked_yield();
3359 }
3360 }
3361
3362 return !directBufferSupportInitializeFailed;
3363}
3364
3365extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, jlong capacity)
3366{
3367 // thread_from_jni_environment() will block if VM is gone.
3368 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
3369
3370 JNIWrapper("jni_NewDirectByteBuffer");
3371 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_ENTRY(env, address, capacity);
3372
3373 if (!directBufferSupportInitializeEnded) {
3374 if (!initializeDirectBufferSupport(env, thread)) {
3375 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(NULL);
3376 return NULL;
3377 }
3378 }
3379
3380 // Being paranoid about accidental sign extension on address
3381 jlong addr = (jlong) ((uintptr_t) address);
3382 // NOTE that package-private DirectByteBuffer constructor currently
3383 // takes int capacity
3384 jint cap = (jint) capacity;
3385 jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap);
3386 HOTSPOT_JNI_NEWDIRECTBYTEBUFFER_RETURN(ret);
3387 return ret;
3388}
3389
3390DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*
3391 , HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_RETURN((void*) _ret_ref));
3392
3393extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
3394{
3395 // thread_from_jni_environment() will block if VM is gone.
3396 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
3397
3398 JNIWrapper("jni_GetDirectBufferAddress");
3399 HOTSPOT_JNI_GETDIRECTBUFFERADDRESS_ENTRY(env, buf);
3400 void* ret = NULL;
3401 DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret);
3402
3403 if (!directBufferSupportInitializeEnded) {
3404 if (!initializeDirectBufferSupport(env, thread)) {
3405 return 0;
3406 }
3407 }
3408
3409 if ((buf != NULL) && (!env->IsInstanceOf(buf, directBufferClass))) {
3410 return 0;
3411 }
3412
3413 ret = (void*)(intptr_t)env->GetLongField(buf, directBufferAddressField);
3414 return ret;
3415}
3416
3417DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong
3418 , HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_RETURN(_ret_ref));
3419
3420extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf)
3421{
3422 // thread_from_jni_environment() will block if VM is gone.
3423 JavaThread* thread = JavaThread::thread_from_jni_environment(env);
3424
3425 JNIWrapper("jni_GetDirectBufferCapacity");
3426 HOTSPOT_JNI_GETDIRECTBUFFERCAPACITY_ENTRY(env, buf);
3427 jlong ret = -1;
3428 DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret);
3429
3430 if (!directBufferSupportInitializeEnded) {
3431 if (!initializeDirectBufferSupport(env, thread)) {
3432 ret = 0;
3433 return ret;
3434 }
3435 }
3436
3437 if (buf == NULL) {
3438 return -1;
3439 }
3440
3441 if (!env->IsInstanceOf(buf, directBufferClass)) {
3442 return -1;
3443 }
3444
3445 // NOTE that capacity is currently an int in the implementation
3446 ret = env->GetIntField(buf, bufferCapacityField);
3447 return ret;
3448}
3449
3450
3451JNI_LEAF(jint, jni_GetVersion(JNIEnv *env))
3452 JNIWrapper("GetVersion");
3453 HOTSPOT_JNI_GETVERSION_ENTRY(env);
3454 HOTSPOT_JNI_GETVERSION_RETURN(CurrentVersion);
3455 return CurrentVersion;
3456JNI_END
3457
3458extern struct JavaVM_ main_vm;
3459
3460JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm))
3461 JNIWrapper("jni_GetJavaVM");
3462 HOTSPOT_JNI_GETJAVAVM_ENTRY(env, (void **) vm);
3463 *vm = (JavaVM *)(&main_vm);
3464 HOTSPOT_JNI_GETJAVAVM_RETURN(JNI_OK);
3465 return JNI_OK;
3466JNI_END
3467
3468
3469JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
3470 JNIWrapper("GetModule");
3471 return Modules::get_module(clazz, THREAD);
3472JNI_END
3473
3474
3475// Structure containing all jni functions
3476struct JNINativeInterface_ jni_NativeInterface = {
3477 NULL,
3478 NULL,
3479 NULL,
3480
3481 NULL,
3482
3483 jni_GetVersion,
3484
3485 jni_DefineClass,
3486 jni_FindClass,
3487
3488 jni_FromReflectedMethod,
3489 jni_FromReflectedField,
3490
3491 jni_ToReflectedMethod,
3492
3493 jni_GetSuperclass,
3494 jni_IsAssignableFrom,
3495
3496 jni_ToReflectedField,
3497
3498 jni_Throw,
3499 jni_ThrowNew,
3500 jni_ExceptionOccurred,
3501 jni_ExceptionDescribe,
3502 jni_ExceptionClear,
3503 jni_FatalError,
3504
3505 jni_PushLocalFrame,
3506 jni_PopLocalFrame,
3507
3508 jni_NewGlobalRef,
3509 jni_DeleteGlobalRef,
3510 jni_DeleteLocalRef,
3511 jni_IsSameObject,
3512
3513 jni_NewLocalRef,
3514 jni_EnsureLocalCapacity,
3515
3516 jni_AllocObject,
3517 jni_NewObject,
3518 jni_NewObjectV,
3519 jni_NewObjectA,
3520
3521 jni_GetObjectClass,
3522 jni_IsInstanceOf,
3523
3524 jni_GetMethodID,
3525
3526 jni_CallObjectMethod,
3527 jni_CallObjectMethodV,
3528 jni_CallObjectMethodA,
3529 jni_CallBooleanMethod,
3530 jni_CallBooleanMethodV,
3531 jni_CallBooleanMethodA,
3532 jni_CallByteMethod,
3533 jni_CallByteMethodV,
3534 jni_CallByteMethodA,
3535 jni_CallCharMethod,
3536 jni_CallCharMethodV,
3537 jni_CallCharMethodA,
3538 jni_CallShortMethod,
3539 jni_CallShortMethodV,
3540 jni_CallShortMethodA,
3541 jni_CallIntMethod,
3542 jni_CallIntMethodV,
3543 jni_CallIntMethodA,
3544 jni_CallLongMethod,
3545 jni_CallLongMethodV,
3546 jni_CallLongMethodA,
3547 jni_CallFloatMethod,
3548 jni_CallFloatMethodV,
3549 jni_CallFloatMethodA,
3550 jni_CallDoubleMethod,
3551 jni_CallDoubleMethodV,
3552 jni_CallDoubleMethodA,
3553 jni_CallVoidMethod,
3554 jni_CallVoidMethodV,
3555 jni_CallVoidMethodA,
3556
3557 jni_CallNonvirtualObjectMethod,
3558 jni_CallNonvirtualObjectMethodV,
3559 jni_CallNonvirtualObjectMethodA,
3560 jni_CallNonvirtualBooleanMethod,
3561 jni_CallNonvirtualBooleanMethodV,
3562 jni_CallNonvirtualBooleanMethodA,
3563 jni_CallNonvirtualByteMethod,
3564 jni_CallNonvirtualByteMethodV,
3565 jni_CallNonvirtualByteMethodA,
3566 jni_CallNonvirtualCharMethod,
3567 jni_CallNonvirtualCharMethodV,
3568 jni_CallNonvirtualCharMethodA,
3569 jni_CallNonvirtualShortMethod,
3570 jni_CallNonvirtualShortMethodV,
3571 jni_CallNonvirtualShortMethodA,
3572 jni_CallNonvirtualIntMethod,
3573 jni_CallNonvirtualIntMethodV,
3574 jni_CallNonvirtualIntMethodA,
3575 jni_CallNonvirtualLongMethod,
3576 jni_CallNonvirtualLongMethodV,
3577 jni_CallNonvirtualLongMethodA,
3578 jni_CallNonvirtualFloatMethod,
3579 jni_CallNonvirtualFloatMethodV,
3580 jni_CallNonvirtualFloatMethodA,
3581 jni_CallNonvirtualDoubleMethod,
3582 jni_CallNonvirtualDoubleMethodV,
3583 jni_CallNonvirtualDoubleMethodA,
3584 jni_CallNonvirtualVoidMethod,
3585 jni_CallNonvirtualVoidMethodV,
3586 jni_CallNonvirtualVoidMethodA,
3587
3588 jni_GetFieldID,
3589
3590 jni_GetObjectField,
3591 jni_GetBooleanField,
3592 jni_GetByteField,
3593 jni_GetCharField,
3594 jni_GetShortField,
3595 jni_GetIntField,
3596 jni_GetLongField,
3597 jni_GetFloatField,
3598 jni_GetDoubleField,
3599
3600 jni_SetObjectField,
3601 jni_SetBooleanField,
3602 jni_SetByteField,
3603 jni_SetCharField,
3604 jni_SetShortField,
3605 jni_SetIntField,
3606 jni_SetLongField,
3607 jni_SetFloatField,
3608 jni_SetDoubleField,
3609
3610 jni_GetStaticMethodID,
3611
3612 jni_CallStaticObjectMethod,
3613 jni_CallStaticObjectMethodV,
3614 jni_CallStaticObjectMethodA,
3615 jni_CallStaticBooleanMethod,
3616 jni_CallStaticBooleanMethodV,
3617 jni_CallStaticBooleanMethodA,
3618 jni_CallStaticByteMethod,
3619 jni_CallStaticByteMethodV,
3620 jni_CallStaticByteMethodA,
3621 jni_CallStaticCharMethod,
3622 jni_CallStaticCharMethodV,
3623 jni_CallStaticCharMethodA,
3624 jni_CallStaticShortMethod,
3625 jni_CallStaticShortMethodV,
3626 jni_CallStaticShortMethodA,
3627 jni_CallStaticIntMethod,
3628 jni_CallStaticIntMethodV,
3629 jni_CallStaticIntMethodA,
3630 jni_CallStaticLongMethod,
3631 jni_CallStaticLongMethodV,
3632 jni_CallStaticLongMethodA,
3633 jni_CallStaticFloatMethod,
3634 jni_CallStaticFloatMethodV,
3635 jni_CallStaticFloatMethodA,
3636 jni_CallStaticDoubleMethod,
3637 jni_CallStaticDoubleMethodV,
3638 jni_CallStaticDoubleMethodA,
3639 jni_CallStaticVoidMethod,
3640 jni_CallStaticVoidMethodV,
3641 jni_CallStaticVoidMethodA,
3642
3643 jni_GetStaticFieldID,
3644
3645 jni_GetStaticObjectField,
3646 jni_GetStaticBooleanField,
3647 jni_GetStaticByteField,
3648 jni_GetStaticCharField,
3649 jni_GetStaticShortField,
3650 jni_GetStaticIntField,
3651 jni_GetStaticLongField,
3652 jni_GetStaticFloatField,
3653 jni_GetStaticDoubleField,
3654
3655 jni_SetStaticObjectField,
3656 jni_SetStaticBooleanField,
3657 jni_SetStaticByteField,
3658 jni_SetStaticCharField,
3659 jni_SetStaticShortField,
3660 jni_SetStaticIntField,
3661 jni_SetStaticLongField,
3662 jni_SetStaticFloatField,
3663 jni_SetStaticDoubleField,
3664
3665 jni_NewString,
3666 jni_GetStringLength,
3667 jni_GetStringChars,
3668 jni_ReleaseStringChars,
3669
3670 jni_NewStringUTF,
3671 jni_GetStringUTFLength,
3672 jni_GetStringUTFChars,
3673 jni_ReleaseStringUTFChars,
3674
3675 jni_GetArrayLength,
3676
3677 jni_NewObjectArray,
3678 jni_GetObjectArrayElement,
3679 jni_SetObjectArrayElement,
3680
3681 jni_NewBooleanArray,
3682 jni_NewByteArray,
3683 jni_NewCharArray,
3684 jni_NewShortArray,
3685 jni_NewIntArray,
3686 jni_NewLongArray,
3687 jni_NewFloatArray,
3688 jni_NewDoubleArray,
3689
3690 jni_GetBooleanArrayElements,
3691 jni_GetByteArrayElements,
3692 jni_GetCharArrayElements,
3693 jni_GetShortArrayElements,
3694 jni_GetIntArrayElements,
3695 jni_GetLongArrayElements,
3696 jni_GetFloatArrayElements,
3697 jni_GetDoubleArrayElements,
3698
3699 jni_ReleaseBooleanArrayElements,
3700 jni_ReleaseByteArrayElements,
3701 jni_ReleaseCharArrayElements,
3702 jni_ReleaseShortArrayElements,
3703 jni_ReleaseIntArrayElements,
3704 jni_ReleaseLongArrayElements,
3705 jni_ReleaseFloatArrayElements,
3706 jni_ReleaseDoubleArrayElements,
3707
3708 jni_GetBooleanArrayRegion,
3709 jni_GetByteArrayRegion,
3710 jni_GetCharArrayRegion,
3711 jni_GetShortArrayRegion,
3712 jni_GetIntArrayRegion,
3713 jni_GetLongArrayRegion,
3714 jni_GetFloatArrayRegion,
3715 jni_GetDoubleArrayRegion,
3716
3717 jni_SetBooleanArrayRegion,
3718 jni_SetByteArrayRegion,
3719 jni_SetCharArrayRegion,
3720 jni_SetShortArrayRegion,
3721 jni_SetIntArrayRegion,
3722 jni_SetLongArrayRegion,
3723 jni_SetFloatArrayRegion,
3724 jni_SetDoubleArrayRegion,
3725
3726 jni_RegisterNatives,
3727 jni_UnregisterNatives,
3728
3729 jni_MonitorEnter,
3730 jni_MonitorExit,
3731
3732 jni_GetJavaVM,
3733
3734 jni_GetStringRegion,
3735 jni_GetStringUTFRegion,
3736
3737 jni_GetPrimitiveArrayCritical,
3738 jni_ReleasePrimitiveArrayCritical,
3739
3740 jni_GetStringCritical,
3741 jni_ReleaseStringCritical,
3742
3743 jni_NewWeakGlobalRef,
3744 jni_DeleteWeakGlobalRef,
3745
3746 jni_ExceptionCheck,
3747
3748 jni_NewDirectByteBuffer,
3749 jni_GetDirectBufferAddress,
3750 jni_GetDirectBufferCapacity,
3751
3752 // New 1_6 features
3753
3754 jni_GetObjectRefType,
3755
3756 // Module features
3757
3758 jni_GetModule
3759};
3760
3761
3762// For jvmti use to modify jni function table.
3763// Java threads in native contiues to run until it is transitioned
3764// to VM at safepoint. Before the transition or before it is blocked
3765// for safepoint it may access jni function table. VM could crash if
3766// any java thread access the jni function table in the middle of memcpy.
3767// To avoid this each function pointers are copied automically.
3768void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) {
3769 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
3770 intptr_t *a = (intptr_t *) jni_functions();
3771 intptr_t *b = (intptr_t *) new_jni_NativeInterface;
3772 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) {
3773 Atomic::store(*b++, a++);
3774 }
3775}
3776
3777void quicken_jni_functions() {
3778 // Replace Get<Primitive>Field with fast versions
3779 if (UseFastJNIAccessors && !JvmtiExport::can_post_field_access()
3780 && !VerifyJNIFields && !CountJNICalls && !CheckJNICalls) {
3781 address func;
3782 func = JNI_FastGetField::generate_fast_get_boolean_field();
3783 if (func != (address)-1) {
3784 jni_NativeInterface.GetBooleanField = (GetBooleanField_t)func;
3785 }
3786 func = JNI_FastGetField::generate_fast_get_byte_field();
3787 if (func != (address)-1) {
3788 jni_NativeInterface.GetByteField = (GetByteField_t)func;
3789 }
3790 func = JNI_FastGetField::generate_fast_get_char_field();
3791 if (func != (address)-1) {
3792 jni_NativeInterface.GetCharField = (GetCharField_t)func;
3793 }
3794 func = JNI_FastGetField::generate_fast_get_short_field();
3795 if (func != (address)-1) {
3796 jni_NativeInterface.GetShortField = (GetShortField_t)func;
3797 }
3798 func = JNI_FastGetField::generate_fast_get_int_field();
3799 if (func != (address)-1) {
3800 jni_NativeInterface.GetIntField = (GetIntField_t)func;
3801 }
3802 func = JNI_FastGetField::generate_fast_get_long_field();
3803 if (func != (address)-1) {
3804 jni_NativeInterface.GetLongField = (GetLongField_t)func;
3805 }
3806 func = JNI_FastGetField::generate_fast_get_float_field();
3807 if (func != (address)-1) {
3808 jni_NativeInterface.GetFloatField = (GetFloatField_t)func;
3809 }
3810 func = JNI_FastGetField::generate_fast_get_double_field();
3811 if (func != (address)-1) {
3812 jni_NativeInterface.GetDoubleField = (GetDoubleField_t)func;
3813 }
3814 }
3815}
3816
3817// Returns the function structure
3818struct JNINativeInterface_* jni_functions() {
3819#if INCLUDE_JNI_CHECK
3820 if (CheckJNICalls) return jni_functions_check();
3821#endif // INCLUDE_JNI_CHECK
3822 return &jni_NativeInterface;
3823}
3824
3825// Returns the function structure
3826struct JNINativeInterface_* jni_functions_nocheck() {
3827 return &jni_NativeInterface;
3828}
3829
3830static void post_thread_start_event(const JavaThread* jt) {
3831 assert(jt != NULL, "invariant");
3832 EventThreadStart event;
3833 if (event.should_commit()) {
3834 event.set_thread(JFR_THREAD_ID(jt));
3835 event.commit();
3836 }
3837}
3838
3839// Invocation API
3840
3841
3842// Forward declaration
3843extern const struct JNIInvokeInterface_ jni_InvokeInterface;
3844
3845// Global invocation API vars
3846volatile int vm_created = 0;
3847// Indicate whether it is safe to recreate VM
3848volatile int safe_to_recreate_vm = 1;
3849struct JavaVM_ main_vm = {&jni_InvokeInterface};
3850
3851
3852#define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */
3853enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL };
3854
3855DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint
3856 , HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_RETURN(_ret_ref));
3857
3858_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
3859 HOTSPOT_JNI_GETDEFAULTJAVAVMINITARGS_ENTRY(args_);
3860 JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_;
3861 jint ret = JNI_ERR;
3862 DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret);
3863
3864 if (Threads::is_supported_jni_version(args->version)) {
3865 ret = JNI_OK;
3866 }
3867 // 1.1 style no longer supported in hotspot.
3868 // According the JNI spec, we should update args->version on return.
3869 // We also use the structure to communicate with launcher about default
3870 // stack size.
3871 if (args->version == JNI_VERSION_1_1) {
3872 args->version = JNI_VERSION_1_2;
3873 // javaStackSize is int in arguments structure
3874 assert(jlong(ThreadStackSize) * K < INT_MAX, "integer overflow");
3875 args->javaStackSize = (jint)(ThreadStackSize * K);
3876 }
3877 return ret;
3878}
3879
3880DT_RETURN_MARK_DECL(CreateJavaVM, jint
3881 , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref));
3882
3883static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) {
3884 HOTSPOT_JNI_CREATEJAVAVM_ENTRY((void **) vm, penv, args);
3885
3886 jint result = JNI_ERR;
3887 DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result);
3888
3889 // We're about to use Atomic::xchg for synchronization. Some Zero
3890 // platforms use the GCC builtin __sync_lock_test_and_set for this,
3891 // but __sync_lock_test_and_set is not guaranteed to do what we want
3892 // on all architectures. So we check it works before relying on it.
3893#if defined(ZERO) && defined(ASSERT)
3894 {
3895 jint a = 0xcafebabe;
3896 jint b = Atomic::xchg((jint) 0xdeadbeef, &a);
3897 void *c = &a;
3898 void *d = Atomic::xchg(&b, &c);
3899 assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works");
3900 assert(c == &b && d == &a, "Atomic::xchg() works");
3901 }
3902#endif // ZERO && ASSERT
3903
3904 // At the moment it's only possible to have one Java VM,
3905 // since some of the runtime state is in global variables.
3906
3907 // We cannot use our mutex locks here, since they only work on
3908 // Threads. We do an atomic compare and exchange to ensure only
3909 // one thread can call this method at a time
3910
3911 // We use Atomic::xchg rather than Atomic::add/dec since on some platforms
3912 // the add/dec implementations are dependent on whether we are running
3913 // on a multiprocessor Atomic::xchg does not have this problem.
3914 if (Atomic::xchg(1, &vm_created) == 1) {
3915 return JNI_EEXIST; // already created, or create attempt in progress
3916 }
3917 if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) {
3918 return JNI_ERR; // someone tried and failed and retry not allowed.
3919 }
3920
3921 assert(vm_created == 1, "vm_created is true during the creation");
3922
3923 /**
3924 * Certain errors during initialization are recoverable and do not
3925 * prevent this method from being called again at a later time
3926 * (perhaps with different arguments). However, at a certain
3927 * point during initialization if an error occurs we cannot allow
3928 * this function to be called again (or it will crash). In those
3929 * situations, the 'canTryAgain' flag is set to false, which atomically
3930 * sets safe_to_recreate_vm to 1, such that any new call to
3931 * JNI_CreateJavaVM will immediately fail using the above logic.
3932 */
3933 bool can_try_again = true;
3934
3935 result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again);
3936 if (result == JNI_OK) {
3937 JavaThread *thread = JavaThread::current();
3938 assert(!thread->has_pending_exception(), "should have returned not OK");
3939 /* thread is thread_in_vm here */
3940 *vm = (JavaVM *)(&main_vm);
3941 *(JNIEnv**)penv = thread->jni_environment();
3942
3943#if INCLUDE_JVMCI
3944 if (EnableJVMCI) {
3945 if (UseJVMCICompiler) {
3946 // JVMCI is initialized on a CompilerThread
3947 if (BootstrapJVMCI) {
3948 JavaThread* THREAD = thread;
3949 JVMCICompiler* compiler = JVMCICompiler::instance(true, CATCH);
3950 compiler->bootstrap(THREAD);
3951 if (HAS_PENDING_EXCEPTION) {
3952 HandleMark hm;
3953 vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
3954 }
3955 }
3956 }
3957 }
3958#endif
3959
3960 // Notify JVMTI
3961 if (JvmtiExport::should_post_thread_life()) {
3962 JvmtiExport::post_thread_start(thread);
3963 }
3964
3965 post_thread_start_event(thread);
3966
3967#ifndef PRODUCT
3968 if (ReplayCompiles) ciReplay::replay(thread);
3969
3970 // Some platforms (like Win*) need a wrapper around these test
3971 // functions in order to properly handle error conditions.
3972 VMError::test_error_handler();
3973#endif
3974
3975 // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving.
3976 ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native);
3977 } else {
3978 // If create_vm exits because of a pending exception, exit with that
3979 // exception. In the future when we figure out how to reclaim memory,
3980 // we may be able to exit with JNI_ERR and allow the calling application
3981 // to continue.
3982 if (Universe::is_fully_initialized()) {
3983 // otherwise no pending exception possible - VM will already have aborted
3984 JavaThread* THREAD = JavaThread::current();
3985 if (HAS_PENDING_EXCEPTION) {
3986 HandleMark hm;
3987 vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION));
3988 }
3989 }
3990
3991 if (can_try_again) {
3992 // reset safe_to_recreate_vm to 1 so that retrial would be possible
3993 safe_to_recreate_vm = 1;
3994 }
3995
3996 // Creation failed. We must reset vm_created
3997 *vm = 0;
3998 *(JNIEnv**)penv = 0;
3999 // reset vm_created last to avoid race condition. Use OrderAccess to
4000 // control both compiler and architectural-based reordering.
4001 OrderAccess::release_store(&vm_created, 0);
4002 }
4003
4004 // Flush stdout and stderr before exit.
4005 fflush(stdout);
4006 fflush(stderr);
4007
4008 return result;
4009
4010}
4011
4012_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) {
4013 jint result = JNI_ERR;
4014 // On Windows, let CreateJavaVM run with SEH protection
4015#ifdef _WIN32
4016 __try {
4017#endif
4018 result = JNI_CreateJavaVM_inner(vm, penv, args);
4019#ifdef _WIN32
4020 } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {
4021 // Nothing to do.
4022 }
4023#endif
4024 return result;
4025}
4026
4027_JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) {
4028 // See bug 4367188, the wrapper can sometimes cause VM crashes
4029 // JNIWrapper("GetCreatedJavaVMs");
4030
4031 HOTSPOT_JNI_GETCREATEDJAVAVMS_ENTRY((void **) vm_buf, bufLen, (uintptr_t *) numVMs);
4032
4033 if (vm_created == 1) {
4034 if (numVMs != NULL) *numVMs = 1;
4035 if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm);
4036 } else {
4037 if (numVMs != NULL) *numVMs = 0;
4038 }
4039 HOTSPOT_JNI_GETCREATEDJAVAVMS_RETURN(JNI_OK);
4040 return JNI_OK;
4041}
4042
4043extern "C" {
4044
4045DT_RETURN_MARK_DECL(DestroyJavaVM, jint
4046 , HOTSPOT_JNI_DESTROYJAVAVM_RETURN(_ret_ref));
4047
4048static jint JNICALL jni_DestroyJavaVM_inner(JavaVM *vm) {
4049 HOTSPOT_JNI_DESTROYJAVAVM_ENTRY(vm);
4050 jint res = JNI_ERR;
4051 DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res);
4052
4053 if (vm_created == 0) {
4054 res = JNI_ERR;
4055 return res;
4056 }
4057
4058 JNIWrapper("DestroyJavaVM");
4059 JNIEnv *env;
4060 JavaVMAttachArgs destroyargs;
4061 destroyargs.version = CurrentVersion;
4062 destroyargs.name = (char *)"DestroyJavaVM";
4063 destroyargs.group = NULL;
4064 res = vm->AttachCurrentThread((void **)&env, (void *)&destroyargs);
4065 if (res != JNI_OK) {
4066 return res;
4067 }
4068
4069 // Since this is not a JVM_ENTRY we have to set the thread state manually before entering.
4070 JavaThread* thread = JavaThread::current();
4071 ThreadStateTransition::transition_from_native(thread, _thread_in_vm);
4072 if (Threads::destroy_vm()) {
4073 // Should not change thread state, VM is gone
4074 vm_created = 0;
4075 res = JNI_OK;
4076 return res;
4077 } else {
4078 ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native);
4079 res = JNI_ERR;
4080 return res;
4081 }
4082}
4083
4084jint JNICALL jni_DestroyJavaVM(JavaVM *vm) {
4085 jint result = JNI_ERR;
4086 // On Windows, we need SEH protection
4087#ifdef _WIN32
4088 __try {
4089#endif
4090 result = jni_DestroyJavaVM_inner(vm);
4091#ifdef _WIN32
4092 } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) {
4093 // Nothing to do.
4094 }
4095#endif
4096 return result;
4097}
4098
4099static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) {
4100 JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args;
4101
4102 // Check below commented out from JDK1.2fcs as well
4103 /*
4104 if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) {
4105 return JNI_EVERSION;
4106 }
4107 */
4108
4109 Thread* t = Thread::current_or_null();
4110 if (t != NULL) {
4111 // If the thread has been attached this operation is a no-op
4112 *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment();
4113 return JNI_OK;
4114 }
4115
4116 // Create a thread and mark it as attaching so it will be skipped by the
4117 // ThreadsListEnumerator - see CR 6404306
4118 JavaThread* thread = new JavaThread(true);
4119
4120 // Set correct safepoint info. The thread is going to call into Java when
4121 // initializing the Java level thread object. Hence, the correct state must
4122 // be set in order for the Safepoint code to deal with it correctly.
4123 thread->set_thread_state(_thread_in_vm);
4124 thread->record_stack_base_and_size();
4125 thread->register_thread_stack_with_NMT();
4126 thread->initialize_thread_current();
4127
4128 if (!os::create_attached_thread(thread)) {
4129 thread->smr_delete();
4130 return JNI_ERR;
4131 }
4132 // Enable stack overflow checks
4133 thread->create_stack_guard_pages();
4134
4135 thread->initialize_tlab();
4136
4137 thread->cache_global_variables();
4138
4139 // Crucial that we do not have a safepoint check for this thread, since it has
4140 // not been added to the Thread list yet.
4141 { Threads_lock->lock_without_safepoint_check();
4142 // This must be inside this lock in order to get FullGCALot to work properly, i.e., to
4143 // avoid this thread trying to do a GC before it is added to the thread-list
4144 thread->set_active_handles(JNIHandleBlock::allocate_block());
4145 Threads::add(thread, daemon);
4146 Threads_lock->unlock();
4147 }
4148 // Create thread group and name info from attach arguments
4149 oop group = NULL;
4150 char* thread_name = NULL;
4151 if (args != NULL && Threads::is_supported_jni_version(args->version)) {
4152 group = JNIHandles::resolve(args->group);
4153 thread_name = args->name; // may be NULL
4154 }
4155 if (group == NULL) group = Universe::main_thread_group();
4156
4157 // Create Java level thread object and attach it to this thread
4158 bool attach_failed = false;
4159 {
4160 EXCEPTION_MARK;
4161 HandleMark hm(THREAD);
4162 Handle thread_group(THREAD, group);
4163 thread->allocate_threadObj(thread_group, thread_name, daemon, THREAD);
4164 if (HAS_PENDING_EXCEPTION) {
4165 CLEAR_PENDING_EXCEPTION;
4166 // cleanup outside the handle mark.
4167 attach_failed = true;
4168 }
4169 }
4170
4171 if (attach_failed) {
4172 // Added missing cleanup
4173 thread->cleanup_failed_attach_current_thread(daemon);
4174 return JNI_ERR;
4175 }
4176
4177 // mark the thread as no longer attaching
4178 // this uses a fence to push the change through so we don't have
4179 // to regrab the threads_lock
4180 thread->set_done_attaching_via_jni();
4181
4182 // Set java thread status.
4183 java_lang_Thread::set_thread_status(thread->threadObj(),
4184 java_lang_Thread::RUNNABLE);
4185
4186 // Notify the debugger
4187 if (JvmtiExport::should_post_thread_life()) {
4188 JvmtiExport::post_thread_start(thread);
4189 }
4190
4191 post_thread_start_event(thread);
4192
4193 *(JNIEnv**)penv = thread->jni_environment();
4194
4195 // Now leaving the VM, so change thread_state. This is normally automatically taken care
4196 // of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by
4197 // using ThreadStateTransition::transition, we do a callback to the safepoint code if
4198 // needed.
4199
4200 ThreadStateTransition::transition(thread, _thread_in_vm, _thread_in_native);
4201
4202 // Perform any platform dependent FPU setup
4203 os::setup_fpu();
4204
4205 return JNI_OK;
4206}
4207
4208
4209jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) {
4210 HOTSPOT_JNI_ATTACHCURRENTTHREAD_ENTRY(vm, penv, _args);
4211 if (vm_created == 0) {
4212 HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR);
4213 return JNI_ERR;
4214 }
4215
4216 JNIWrapper("AttachCurrentThread");
4217 jint ret = attach_current_thread(vm, penv, _args, false);
4218 HOTSPOT_JNI_ATTACHCURRENTTHREAD_RETURN(ret);
4219 return ret;
4220}
4221
4222
4223jint JNICALL jni_DetachCurrentThread(JavaVM *vm) {
4224 HOTSPOT_JNI_DETACHCURRENTTHREAD_ENTRY(vm);
4225
4226 JNIWrapper("DetachCurrentThread");
4227
4228 // If the thread has already been detached the operation is a no-op
4229 if (Thread::current_or_null() == NULL) {
4230 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK);
4231 return JNI_OK;
4232 }
4233
4234 VM_Exit::block_if_vm_exited();
4235
4236 JavaThread* thread = JavaThread::current();
4237 if (thread->has_last_Java_frame()) {
4238 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN((uint32_t) JNI_ERR);
4239 // Can't detach a thread that's running java, that can't work.
4240 return JNI_ERR;
4241 }
4242
4243 // Safepoint support. Have to do call-back to safepoint code, if in the
4244 // middle of a safepoint operation
4245 ThreadStateTransition::transition_from_native(thread, _thread_in_vm);
4246
4247 // XXX: Note that JavaThread::exit() call below removes the guards on the
4248 // stack pages set up via enable_stack_{red,yellow}_zone() calls
4249 // above in jni_AttachCurrentThread. Unfortunately, while the setting
4250 // of the guards is visible in jni_AttachCurrentThread above,
4251 // the removal of the guards is buried below in JavaThread::exit()
4252 // here. The abstraction should be more symmetrically either exposed
4253 // or hidden (e.g. it could probably be hidden in the same
4254 // (platform-dependent) methods where we do alternate stack
4255 // maintenance work?)
4256 thread->exit(false, JavaThread::jni_detach);
4257 thread->smr_delete();
4258
4259 HOTSPOT_JNI_DETACHCURRENTTHREAD_RETURN(JNI_OK);
4260 return JNI_OK;
4261}
4262
4263DT_RETURN_MARK_DECL(GetEnv, jint
4264 , HOTSPOT_JNI_GETENV_RETURN(_ret_ref));
4265
4266jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) {
4267 HOTSPOT_JNI_GETENV_ENTRY(vm, penv, version);
4268 jint ret = JNI_ERR;
4269 DT_RETURN_MARK(GetEnv, jint, (const jint&)ret);
4270
4271 if (vm_created == 0) {
4272 *penv = NULL;
4273 ret = JNI_EDETACHED;
4274 return ret;
4275 }
4276
4277 if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) {
4278 return ret;
4279 }
4280
4281#ifndef JVMPI_VERSION_1
4282// need these in order to be polite about older agents
4283#define JVMPI_VERSION_1 ((jint)0x10000001)
4284#define JVMPI_VERSION_1_1 ((jint)0x10000002)
4285#define JVMPI_VERSION_1_2 ((jint)0x10000003)
4286#endif // !JVMPI_VERSION_1
4287
4288 Thread* thread = Thread::current_or_null();
4289 if (thread != NULL && thread->is_Java_thread()) {
4290 if (Threads::is_supported_jni_version_including_1_1(version)) {
4291 *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment();
4292 ret = JNI_OK;
4293 return ret;
4294
4295 } else if (version == JVMPI_VERSION_1 ||
4296 version == JVMPI_VERSION_1_1 ||
4297 version == JVMPI_VERSION_1_2) {
4298 tty->print_cr("ERROR: JVMPI, an experimental interface, is no longer supported.");
4299 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");
4300 ret = JNI_EVERSION;
4301 return ret;
4302 } else if (JvmtiExport::is_jvmdi_version(version)) {
4303 tty->print_cr("FATAL ERROR: JVMDI is no longer supported.");
4304 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI).");
4305 ret = JNI_EVERSION;
4306 return ret;
4307 } else {
4308 *penv = NULL;
4309 ret = JNI_EVERSION;
4310 return ret;
4311 }
4312 } else {
4313 *penv = NULL;
4314 ret = JNI_EDETACHED;
4315 return ret;
4316 }
4317}
4318
4319
4320jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) {
4321 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_ENTRY(vm, penv, _args);
4322 if (vm_created == 0) {
4323 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN((uint32_t) JNI_ERR);
4324 return JNI_ERR;
4325 }
4326
4327 JNIWrapper("AttachCurrentThreadAsDaemon");
4328 jint ret = attach_current_thread(vm, penv, _args, true);
4329 HOTSPOT_JNI_ATTACHCURRENTTHREADASDAEMON_RETURN(ret);
4330 return ret;
4331}
4332
4333
4334} // End extern "C"
4335
4336const struct JNIInvokeInterface_ jni_InvokeInterface = {
4337 NULL,
4338 NULL,
4339 NULL,
4340
4341 jni_DestroyJavaVM,
4342 jni_AttachCurrentThread,
4343 jni_DetachCurrentThread,
4344 jni_GetEnv,
4345 jni_AttachCurrentThreadAsDaemon
4346};
4347