Mercurial > hg > graal-jvmci-8
annotate src/share/vm/prims/jni.cpp @ 3249:e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes
author | johnc |
---|---|
date | Thu, 07 Apr 2011 09:53:20 -0700 |
parents | c7f3d0b4570f |
children | be4ca325525a 04760e41b01e |
rev | line source |
---|---|
0 | 1 /* |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1490
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/classLoader.hpp" | |
27 #include "classfile/javaClasses.hpp" | |
28 #include "classfile/symbolTable.hpp" | |
29 #include "classfile/systemDictionary.hpp" | |
30 #include "classfile/vmSymbols.hpp" | |
31 #include "interpreter/linkResolver.hpp" | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
32 #ifndef SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
33 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
34 #endif // SERIALGC |
1972 | 35 #include "memory/allocation.inline.hpp" |
36 #include "memory/gcLocker.inline.hpp" | |
37 #include "memory/oopFactory.hpp" | |
38 #include "memory/universe.inline.hpp" | |
39 #include "oops/instanceKlass.hpp" | |
40 #include "oops/instanceOop.hpp" | |
41 #include "oops/markOop.hpp" | |
42 #include "oops/methodOop.hpp" | |
43 #include "oops/objArrayKlass.hpp" | |
44 #include "oops/objArrayOop.hpp" | |
45 #include "oops/oop.inline.hpp" | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
46 #include "oops/symbol.hpp" |
1972 | 47 #include "oops/typeArrayKlass.hpp" |
48 #include "oops/typeArrayOop.hpp" | |
49 #include "prims/jni.h" | |
50 #include "prims/jniCheck.hpp" | |
51 #include "prims/jniFastGetField.hpp" | |
52 #include "prims/jvm.h" | |
53 #include "prims/jvm_misc.hpp" | |
54 #include "prims/jvmtiExport.hpp" | |
55 #include "prims/jvmtiThreadState.hpp" | |
56 #include "runtime/compilationPolicy.hpp" | |
57 #include "runtime/fieldDescriptor.hpp" | |
58 #include "runtime/fprofiler.hpp" | |
59 #include "runtime/handles.inline.hpp" | |
60 #include "runtime/interfaceSupport.hpp" | |
61 #include "runtime/java.hpp" | |
62 #include "runtime/javaCalls.hpp" | |
63 #include "runtime/jfieldIDWorkaround.hpp" | |
64 #include "runtime/reflection.hpp" | |
65 #include "runtime/sharedRuntime.hpp" | |
66 #include "runtime/signature.hpp" | |
67 #include "runtime/vm_operations.hpp" | |
68 #include "services/runtimeService.hpp" | |
69 #include "utilities/defaultStream.hpp" | |
70 #include "utilities/dtrace.hpp" | |
71 #include "utilities/events.hpp" | |
72 #include "utilities/histogram.hpp" | |
73 #ifdef TARGET_ARCH_x86 | |
74 # include "jniTypes_x86.hpp" | |
75 #endif | |
76 #ifdef TARGET_ARCH_sparc | |
77 # include "jniTypes_sparc.hpp" | |
78 #endif | |
79 #ifdef TARGET_ARCH_zero | |
80 # include "jniTypes_zero.hpp" | |
81 #endif | |
82 #ifdef TARGET_OS_FAMILY_linux | |
83 # include "os_linux.inline.hpp" | |
84 # include "thread_linux.inline.hpp" | |
85 #endif | |
86 #ifdef TARGET_OS_FAMILY_solaris | |
87 # include "os_solaris.inline.hpp" | |
88 # include "thread_solaris.inline.hpp" | |
89 #endif | |
90 #ifdef TARGET_OS_FAMILY_windows | |
91 # include "os_windows.inline.hpp" | |
92 # include "thread_windows.inline.hpp" | |
93 #endif | |
0 | 94 |
95 static jint CurrentVersion = JNI_VERSION_1_6; | |
96 | |
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) \ | |
119 HS_DTRACE_PROBE_DECL1(hotspot_jni, name##__return, type); \ | |
120 DTRACE_ONLY( \ | |
121 class DTraceReturnProbeMark_##name { \ | |
122 public: \ | |
123 const type& _ret_ref; \ | |
124 DTraceReturnProbeMark_##name(const type& v) : _ret_ref(v) {} \ | |
125 ~DTraceReturnProbeMark_##name() { \ | |
126 HS_DTRACE_PROBE1(hotspot_jni, name##__return, _ret_ref); \ | |
127 } \ | |
128 } \ | |
129 ) | |
130 // Void functions are simpler since there's no return value | |
131 #define DT_VOID_RETURN_MARK_DECL(name) \ | |
132 HS_DTRACE_PROBE_DECL0(hotspot_jni, name##__return); \ | |
133 DTRACE_ONLY( \ | |
134 class DTraceReturnProbeMark_##name { \ | |
135 public: \ | |
136 ~DTraceReturnProbeMark_##name() { \ | |
137 HS_DTRACE_PROBE0(hotspot_jni, name##__return); \ | |
138 } \ | |
139 } \ | |
140 ) | |
141 | |
142 | |
143 // Place these macros in the function to mark the return. Non-void | |
144 // functions need the type and address of the return value. | |
145 #define DT_RETURN_MARK(name, type, ref) \ | |
146 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark(ref) ) | |
147 #define DT_VOID_RETURN_MARK(name) \ | |
148 DTRACE_ONLY( DTraceReturnProbeMark_##name dtrace_return_mark ) | |
149 | |
150 | |
151 // Use these to select distinct code for floating-point vs. non-floating point | |
152 // situations. Used from within common macros where we need slightly | |
153 // different behavior for Float/Double | |
154 #define FP_SELECT_Boolean(intcode, fpcode) intcode | |
155 #define FP_SELECT_Byte(intcode, fpcode) intcode | |
156 #define FP_SELECT_Char(intcode, fpcode) intcode | |
157 #define FP_SELECT_Short(intcode, fpcode) intcode | |
158 #define FP_SELECT_Object(intcode, fpcode) intcode | |
159 #define FP_SELECT_Int(intcode, fpcode) intcode | |
160 #define FP_SELECT_Long(intcode, fpcode) intcode | |
161 #define FP_SELECT_Float(intcode, fpcode) fpcode | |
162 #define FP_SELECT_Double(intcode, fpcode) fpcode | |
163 #define FP_SELECT(TypeName, intcode, fpcode) \ | |
164 FP_SELECT_##TypeName(intcode, fpcode) | |
165 | |
166 #define COMMA , | |
167 | |
168 // Choose DT_RETURN_MARK macros based on the type: float/double -> void | |
169 // (dtrace doesn't do FP yet) | |
170 #define DT_RETURN_MARK_DECL_FOR(TypeName, name, type) \ | |
171 FP_SELECT(TypeName, \ | |
172 DT_RETURN_MARK_DECL(name, type), DT_VOID_RETURN_MARK_DECL(name) ) | |
173 #define DT_RETURN_MARK_FOR(TypeName, name, type, ref) \ | |
174 FP_SELECT(TypeName, \ | |
175 DT_RETURN_MARK(name, type, ref), DT_VOID_RETURN_MARK(name) ) | |
176 | |
177 | |
178 // out-of-line helpers for class jfieldIDWorkaround: | |
179 | |
180 bool jfieldIDWorkaround::is_valid_jfieldID(klassOop k, jfieldID id) { | |
181 if (jfieldIDWorkaround::is_instance_jfieldID(k, id)) { | |
182 uintptr_t as_uint = (uintptr_t) id; | |
183 intptr_t offset = raw_instance_offset(id); | |
184 if (is_checked_jfieldID(id)) { | |
185 if (!klass_hash_ok(k, id)) { | |
186 return false; | |
187 } | |
188 } | |
189 return instanceKlass::cast(k)->contains_field_offset(offset); | |
190 } else { | |
191 JNIid* result = (JNIid*) id; | |
192 #ifdef ASSERT | |
193 return result != NULL && result->is_static_field_id(); | |
194 #else | |
195 return result != NULL; | |
196 #endif | |
197 } | |
198 } | |
199 | |
200 | |
201 intptr_t jfieldIDWorkaround::encode_klass_hash(klassOop k, intptr_t offset) { | |
202 if (offset <= small_offset_mask) { | |
203 klassOop field_klass = k; | |
204 klassOop super_klass = Klass::cast(field_klass)->super(); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
205 // With compressed oops the most super class with nonstatic fields would |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
206 // be the owner of fields embedded in the header. |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
207 while (instanceKlass::cast(super_klass)->has_nonstatic_fields() && |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
208 instanceKlass::cast(super_klass)->contains_field_offset(offset)) { |
0 | 209 field_klass = super_klass; // super contains the field also |
210 super_klass = Klass::cast(field_klass)->super(); | |
211 } | |
212 debug_only(No_Safepoint_Verifier nosafepoint;) | |
213 uintptr_t klass_hash = field_klass->identity_hash(); | |
214 return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place; | |
215 } else { | |
216 #if 0 | |
217 #ifndef PRODUCT | |
218 { | |
219 ResourceMark rm; | |
220 warning("VerifyJNIFields: long offset %d in %s", offset, Klass::cast(k)->external_name()); | |
221 } | |
222 #endif | |
223 #endif | |
224 return 0; | |
225 } | |
226 } | |
227 | |
228 bool jfieldIDWorkaround::klass_hash_ok(klassOop k, jfieldID id) { | |
229 uintptr_t as_uint = (uintptr_t) id; | |
230 intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask; | |
231 do { | |
232 debug_only(No_Safepoint_Verifier nosafepoint;) | |
233 // Could use a non-blocking query for identity_hash here... | |
234 if ((k->identity_hash() & klass_mask) == klass_hash) | |
235 return true; | |
236 k = Klass::cast(k)->super(); | |
237 } while (k != NULL); | |
238 return false; | |
239 } | |
240 | |
241 void jfieldIDWorkaround::verify_instance_jfieldID(klassOop k, jfieldID id) { | |
242 guarantee(jfieldIDWorkaround::is_instance_jfieldID(k, id), "must be an instance field" ); | |
243 uintptr_t as_uint = (uintptr_t) id; | |
244 intptr_t offset = raw_instance_offset(id); | |
245 if (VerifyJNIFields) { | |
246 if (is_checked_jfieldID(id)) { | |
247 guarantee(klass_hash_ok(k, id), | |
248 "Bug in native code: jfieldID class must match object"); | |
249 } else { | |
250 #if 0 | |
251 #ifndef PRODUCT | |
252 if (Verbose) { | |
253 ResourceMark rm; | |
254 warning("VerifyJNIFields: unverified offset %d for %s", offset, Klass::cast(k)->external_name()); | |
255 } | |
256 #endif | |
257 #endif | |
258 } | |
259 } | |
260 guarantee(instanceKlass::cast(k)->contains_field_offset(offset), | |
261 "Bug in native code: jfieldID offset must address interior of object"); | |
262 } | |
263 | |
264 // Pick a reasonable higher bound for local capacity requested | |
265 // for EnsureLocalCapacity and PushLocalFrame. We don't want it too | |
266 // high because a test (or very unusual application) may try to allocate | |
267 // that many handles and run out of swap space. An implementation is | |
268 // permitted to allocate more handles than the ensured capacity, so this | |
269 // value is set high enough to prevent compatibility problems. | |
270 const int MAX_REASONABLE_LOCAL_CAPACITY = 4*K; | |
271 | |
272 | |
273 // Wrapper to trace JNI functions | |
274 | |
275 #ifdef ASSERT | |
276 Histogram* JNIHistogram; | |
277 static volatile jint JNIHistogram_lock = 0; | |
278 | |
279 class JNITraceWrapper : public StackObj { | |
280 public: | |
281 JNITraceWrapper(const char* format, ...) { | |
282 if (TraceJNICalls) { | |
283 va_list ap; | |
284 va_start(ap, format); | |
285 tty->print("JNI "); | |
286 tty->vprint_cr(format, ap); | |
287 va_end(ap); | |
288 } | |
289 } | |
290 }; | |
291 | |
292 class JNIHistogramElement : public HistogramElement { | |
293 public: | |
294 JNIHistogramElement(const char* name); | |
295 }; | |
296 | |
297 JNIHistogramElement::JNIHistogramElement(const char* elementName) { | |
298 _name = elementName; | |
299 uintx count = 0; | |
300 | |
301 while (Atomic::cmpxchg(1, &JNIHistogram_lock, 0) != 0) { | |
302 while (OrderAccess::load_acquire(&JNIHistogram_lock) != 0) { | |
303 count +=1; | |
304 if ( (WarnOnStalledSpinLock > 0) | |
305 && (count % WarnOnStalledSpinLock == 0)) { | |
306 warning("JNIHistogram_lock seems to be stalled"); | |
307 } | |
308 } | |
309 } | |
310 | |
311 | |
312 if(JNIHistogram == NULL) | |
313 JNIHistogram = new Histogram("JNI Call Counts",100); | |
314 | |
315 JNIHistogram->add_element(this); | |
316 Atomic::dec(&JNIHistogram_lock); | |
317 } | |
318 | |
319 #define JNICountWrapper(arg) \ | |
320 static JNIHistogramElement* e = new JNIHistogramElement(arg); \ | |
321 /* There is a MT-race condition in VC++. So we need to make sure that that e has been initialized */ \ | |
322 if (e != NULL) e->increment_count() | |
323 #define JNIWrapper(arg) JNICountWrapper(arg); JNITraceWrapper(arg) | |
324 #else | |
325 #define JNIWrapper(arg) | |
326 #endif | |
327 | |
328 | |
329 // Implementation of JNI entries | |
330 | |
331 DT_RETURN_MARK_DECL(DefineClass, jclass); | |
332 | |
333 JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderRef, | |
334 const jbyte *buf, jsize bufLen)) | |
335 JNIWrapper("DefineClass"); | |
336 | |
337 DTRACE_PROBE5(hotspot_jni, DefineClass__entry, | |
338 env, name, loaderRef, buf, bufLen); | |
339 jclass cls = NULL; | |
340 DT_RETURN_MARK(DefineClass, jclass, (const jclass&)cls); | |
341 | |
342 // Since exceptions can be thrown, class initialization can take place | |
343 // if name is NULL no check for class name in .class stream has to be made. | |
344 if (name != NULL) { | |
345 const int str_len = (int)strlen(name); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
346 if (str_len > Symbol::max_length()) { |
0 | 347 // It's impossible to create this class; the name cannot fit |
348 // into the constant pool. | |
349 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); | |
350 } | |
351 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
352 TempNewSymbol class_name = SymbolTable::new_symbol(name, THREAD); |
0 | 353 |
354 ResourceMark rm(THREAD); | |
355 ClassFileStream st((u1*) buf, bufLen, NULL); | |
356 Handle class_loader (THREAD, JNIHandles::resolve(loaderRef)); | |
357 | |
358 if (UsePerfData && !class_loader.is_null()) { | |
359 // check whether the current caller thread holds the lock or not. | |
360 // If not, increment the corresponding counter | |
361 if (ObjectSynchronizer:: | |
362 query_lock_ownership((JavaThread*)THREAD, class_loader) != | |
363 ObjectSynchronizer::owner_self) { | |
364 ClassLoader::sync_JNIDefineClassLockFreeCounter()->inc(); | |
365 } | |
366 } | |
367 klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader, | |
973
ad6585fd4087
6830542: Performance: JVM_DefineClass already verified.
acorn
parents:
657
diff
changeset
|
368 Handle(), &st, true, |
ad6585fd4087
6830542: Performance: JVM_DefineClass already verified.
acorn
parents:
657
diff
changeset
|
369 CHECK_NULL); |
0 | 370 |
657
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
371 if (TraceClassResolution && k != NULL) { |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
372 trace_class_resolution(k); |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
373 } |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
374 |
0 | 375 cls = (jclass)JNIHandles::make_local( |
376 env, Klass::cast(k)->java_mirror()); | |
377 return cls; | |
378 JNI_END | |
379 | |
380 | |
381 | |
382 static bool first_time_FindClass = true; | |
383 | |
384 DT_RETURN_MARK_DECL(FindClass, jclass); | |
385 | |
386 JNI_ENTRY(jclass, jni_FindClass(JNIEnv *env, const char *name)) | |
387 JNIWrapper("FindClass"); | |
388 DTRACE_PROBE2(hotspot_jni, FindClass__entry, env, name); | |
389 | |
390 jclass result = NULL; | |
391 DT_RETURN_MARK(FindClass, jclass, (const jclass&)result); | |
392 | |
393 // Remember if we are the first invocation of jni_FindClass | |
394 bool first_time = first_time_FindClass; | |
395 first_time_FindClass = false; | |
396 | |
397 // Sanity check the name: it cannot be null or larger than the maximum size | |
398 // name we can fit in the constant pool. | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
399 if (name == NULL || (int)strlen(name) > Symbol::max_length()) { |
0 | 400 THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); |
401 } | |
402 | |
403 //%note jni_3 | |
404 Handle loader; | |
405 Handle protection_domain; | |
406 // Find calling class | |
407 instanceKlassHandle k (THREAD, thread->security_get_caller_class(0)); | |
408 if (k.not_null()) { | |
409 loader = Handle(THREAD, k->class_loader()); | |
410 // Special handling to make sure JNI_OnLoad and JNI_OnUnload are executed | |
411 // in the correct class context. | |
412 if (loader.is_null() && | |
413 k->name() == vmSymbols::java_lang_ClassLoader_NativeLibrary()) { | |
414 JavaValue result(T_OBJECT); | |
415 JavaCalls::call_static(&result, k, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
416 vmSymbols::getFromClass_name(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
417 vmSymbols::void_class_signature(), |
0 | 418 thread); |
419 if (HAS_PENDING_EXCEPTION) { | |
420 Handle ex(thread, thread->pending_exception()); | |
421 CLEAR_PENDING_EXCEPTION; | |
422 THROW_HANDLE_0(ex); | |
423 } | |
424 oop mirror = (oop) result.get_jobject(); | |
425 loader = Handle(THREAD, | |
426 instanceKlass::cast(java_lang_Class::as_klassOop(mirror))->class_loader()); | |
427 protection_domain = Handle(THREAD, | |
428 instanceKlass::cast(java_lang_Class::as_klassOop(mirror))->protection_domain()); | |
429 } | |
430 } else { | |
431 // We call ClassLoader.getSystemClassLoader to obtain the system class loader. | |
432 loader = Handle(THREAD, SystemDictionary::java_system_loader()); | |
433 } | |
434 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
435 TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL); |
0 | 436 result = find_class_from_class_loader(env, sym, true, loader, |
437 protection_domain, true, thread); | |
438 | |
657
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
439 if (TraceClassResolution && result != NULL) { |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
440 trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
441 } |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
442 |
0 | 443 // If we were the first invocation of jni_FindClass, we enable compilation again |
444 // rather than just allowing invocation counter to overflow and decay. | |
445 // Controlled by flag DelayCompilationDuringStartup. | |
446 if (first_time && !CompileTheWorld) | |
447 CompilationPolicy::completed_vm_startup(); | |
448 | |
449 return result; | |
450 JNI_END | |
451 | |
452 DT_RETURN_MARK_DECL(FromReflectedMethod, jmethodID); | |
453 | |
454 JNI_ENTRY(jmethodID, jni_FromReflectedMethod(JNIEnv *env, jobject method)) | |
455 JNIWrapper("FromReflectedMethod"); | |
456 DTRACE_PROBE2(hotspot_jni, FromReflectedMethod__entry, env, method); | |
457 jmethodID ret = NULL; | |
458 DT_RETURN_MARK(FromReflectedMethod, jmethodID, (const jmethodID&)ret); | |
459 | |
460 // method is a handle to a java.lang.reflect.Method object | |
461 oop reflected = JNIHandles::resolve_non_null(method); | |
462 oop mirror = NULL; | |
463 int slot = 0; | |
464 | |
1142 | 465 if (reflected->klass() == SystemDictionary::reflect_Constructor_klass()) { |
0 | 466 mirror = java_lang_reflect_Constructor::clazz(reflected); |
467 slot = java_lang_reflect_Constructor::slot(reflected); | |
468 } else { | |
1142 | 469 assert(reflected->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); |
0 | 470 mirror = java_lang_reflect_Method::clazz(reflected); |
471 slot = java_lang_reflect_Method::slot(reflected); | |
472 } | |
473 klassOop k = java_lang_Class::as_klassOop(mirror); | |
474 | |
475 KlassHandle k1(THREAD, k); | |
476 // Make sure class is initialized before handing id's out to methods | |
477 Klass::cast(k1())->initialize(CHECK_NULL); | |
478 methodOop m = instanceKlass::cast(k1())->method_with_idnum(slot); | |
479 ret = m==NULL? NULL : m->jmethod_id(); // return NULL if reflected method deleted | |
480 return ret; | |
481 JNI_END | |
482 | |
483 DT_RETURN_MARK_DECL(FromReflectedField, jfieldID); | |
484 | |
485 JNI_ENTRY(jfieldID, jni_FromReflectedField(JNIEnv *env, jobject field)) | |
486 JNIWrapper("FromReflectedField"); | |
487 DTRACE_PROBE2(hotspot_jni, FromReflectedField__entry, env, field); | |
488 jfieldID ret = NULL; | |
489 DT_RETURN_MARK(FromReflectedField, jfieldID, (const jfieldID&)ret); | |
490 | |
491 // field is a handle to a java.lang.reflect.Field object | |
492 oop reflected = JNIHandles::resolve_non_null(field); | |
493 oop mirror = java_lang_reflect_Field::clazz(reflected); | |
494 klassOop k = java_lang_Class::as_klassOop(mirror); | |
495 int slot = java_lang_reflect_Field::slot(reflected); | |
496 int modifiers = java_lang_reflect_Field::modifiers(reflected); | |
497 | |
498 KlassHandle k1(THREAD, k); | |
499 // Make sure class is initialized before handing id's out to fields | |
500 Klass::cast(k1())->initialize(CHECK_NULL); | |
501 | |
502 // First check if this is a static field | |
503 if (modifiers & JVM_ACC_STATIC) { | |
504 intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); | |
505 JNIid* id = instanceKlass::cast(k1())->jni_id_for(offset); | |
506 assert(id != NULL, "corrupt Field object"); | |
507 debug_only(id->set_is_static_field_id();) | |
508 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the klassOop | |
509 ret = jfieldIDWorkaround::to_static_jfieldID(id); | |
510 return ret; | |
511 } | |
512 | |
513 // The slot is the index of the field description in the field-array | |
514 // The jfieldID is the offset of the field within the object | |
515 // It may also have hash bits for k, if VerifyJNIFields is turned on. | |
516 intptr_t offset = instanceKlass::cast(k1())->offset_from_fields( slot ); | |
517 assert(instanceKlass::cast(k1())->contains_field_offset(offset), "stay within object"); | |
518 ret = jfieldIDWorkaround::to_instance_jfieldID(k1(), offset); | |
519 return ret; | |
520 JNI_END | |
521 | |
522 DT_RETURN_MARK_DECL(ToReflectedMethod, jobject); | |
523 | |
524 JNI_ENTRY(jobject, jni_ToReflectedMethod(JNIEnv *env, jclass cls, jmethodID method_id, jboolean isStatic)) | |
525 JNIWrapper("ToReflectedMethod"); | |
526 DTRACE_PROBE4(hotspot_jni, ToReflectedMethod__entry, env, cls, method_id, isStatic); | |
527 jobject ret = NULL; | |
528 DT_RETURN_MARK(ToReflectedMethod, jobject, (const jobject&)ret); | |
529 | |
530 methodHandle m (THREAD, JNIHandles::resolve_jmethod_id(method_id)); | |
531 assert(m->is_static() == (isStatic != 0), "jni_ToReflectedMethod access flags doesn't match"); | |
532 oop reflection_method; | |
533 if (m->is_initializer()) { | |
534 reflection_method = Reflection::new_constructor(m, CHECK_NULL); | |
535 } else { | |
536 reflection_method = Reflection::new_method(m, UseNewReflection, false, CHECK_NULL); | |
537 } | |
538 ret = JNIHandles::make_local(env, reflection_method); | |
539 return ret; | |
540 JNI_END | |
541 | |
542 DT_RETURN_MARK_DECL(GetSuperclass, jclass); | |
543 | |
544 JNI_ENTRY(jclass, jni_GetSuperclass(JNIEnv *env, jclass sub)) | |
545 JNIWrapper("GetSuperclass"); | |
546 DTRACE_PROBE2(hotspot_jni, GetSuperclass__entry, env, sub); | |
547 jclass obj = NULL; | |
548 DT_RETURN_MARK(GetSuperclass, jclass, (const jclass&)obj); | |
549 | |
550 oop mirror = JNIHandles::resolve_non_null(sub); | |
551 // primitive classes return NULL | |
552 if (java_lang_Class::is_primitive(mirror)) return NULL; | |
553 | |
554 // Rules of Class.getSuperClass as implemented by KLass::java_super: | |
555 // arrays return Object | |
556 // interfaces return NULL | |
557 // proper classes return Klass::super() | |
558 klassOop k = java_lang_Class::as_klassOop(mirror); | |
559 if (Klass::cast(k)->is_interface()) return NULL; | |
560 | |
561 // return mirror for superclass | |
562 klassOop super = Klass::cast(k)->java_super(); | |
563 // super2 is the value computed by the compiler's getSuperClass intrinsic: | |
564 debug_only(klassOop super2 = ( Klass::cast(k)->oop_is_javaArray() | |
1142 | 565 ? SystemDictionary::Object_klass() |
0 | 566 : Klass::cast(k)->super() ) ); |
567 assert(super == super2, | |
568 "java_super computation depends on interface, array, other super"); | |
569 obj = (super == NULL) ? NULL : (jclass) JNIHandles::make_local(Klass::cast(super)->java_mirror()); | |
570 return obj; | |
571 JNI_END | |
572 | |
573 JNI_QUICK_ENTRY(jboolean, jni_IsAssignableFrom(JNIEnv *env, jclass sub, jclass super)) | |
574 JNIWrapper("IsSubclassOf"); | |
575 DTRACE_PROBE3(hotspot_jni, IsAssignableFrom__entry, env, sub, super); | |
576 oop sub_mirror = JNIHandles::resolve_non_null(sub); | |
577 oop super_mirror = JNIHandles::resolve_non_null(super); | |
578 if (java_lang_Class::is_primitive(sub_mirror) || | |
579 java_lang_Class::is_primitive(super_mirror)) { | |
580 jboolean ret = (sub_mirror == super_mirror); | |
581 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); | |
582 return ret; | |
583 } | |
584 klassOop sub_klass = java_lang_Class::as_klassOop(sub_mirror); | |
585 klassOop super_klass = java_lang_Class::as_klassOop(super_mirror); | |
586 assert(sub_klass != NULL && super_klass != NULL, "invalid arguments to jni_IsAssignableFrom"); | |
587 jboolean ret = Klass::cast(sub_klass)->is_subtype_of(super_klass) ? | |
588 JNI_TRUE : JNI_FALSE; | |
589 DTRACE_PROBE1(hotspot_jni, IsAssignableFrom__return, ret); | |
590 return ret; | |
591 JNI_END | |
592 | |
593 DT_RETURN_MARK_DECL(Throw, jint); | |
594 | |
595 JNI_ENTRY(jint, jni_Throw(JNIEnv *env, jthrowable obj)) | |
596 JNIWrapper("Throw"); | |
597 DTRACE_PROBE2(hotspot_jni, Throw__entry, env, obj); | |
598 jint ret = JNI_OK; | |
599 DT_RETURN_MARK(Throw, jint, (const jint&)ret); | |
600 | |
601 THROW_OOP_(JNIHandles::resolve(obj), JNI_OK); | |
602 ShouldNotReachHere(); | |
603 JNI_END | |
604 | |
605 DT_RETURN_MARK_DECL(ThrowNew, jint); | |
606 | |
607 JNI_ENTRY(jint, jni_ThrowNew(JNIEnv *env, jclass clazz, const char *message)) | |
608 JNIWrapper("ThrowNew"); | |
609 DTRACE_PROBE3(hotspot_jni, ThrowNew__entry, env, clazz, message); | |
610 jint ret = JNI_OK; | |
611 DT_RETURN_MARK(ThrowNew, jint, (const jint&)ret); | |
612 | |
613 instanceKlass* k = instanceKlass::cast(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
614 Symbol* name = k->name(); |
0 | 615 Handle class_loader (THREAD, k->class_loader()); |
616 Handle protection_domain (THREAD, k->protection_domain()); | |
617 THROW_MSG_LOADER_(name, (char *)message, class_loader, protection_domain, JNI_OK); | |
618 ShouldNotReachHere(); | |
619 JNI_END | |
620 | |
621 | |
622 // JNI functions only transform a pending async exception to a synchronous | |
623 // exception in ExceptionOccurred and ExceptionCheck calls, since | |
624 // delivering an async exception in other places won't change the native | |
625 // code's control flow and would be harmful when native code further calls | |
626 // JNI functions with a pending exception. Async exception is also checked | |
627 // during the call, so ExceptionOccurred/ExceptionCheck won't return | |
628 // false but deliver the async exception at the very end during | |
629 // state transition. | |
630 | |
631 static void jni_check_async_exceptions(JavaThread *thread) { | |
632 assert(thread == Thread::current(), "must be itself"); | |
633 thread->check_and_handle_async_exceptions(); | |
634 } | |
635 | |
636 JNI_ENTRY_NO_PRESERVE(jthrowable, jni_ExceptionOccurred(JNIEnv *env)) | |
637 JNIWrapper("ExceptionOccurred"); | |
638 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__entry, env); | |
639 jni_check_async_exceptions(thread); | |
640 oop exception = thread->pending_exception(); | |
641 jthrowable ret = (jthrowable) JNIHandles::make_local(env, exception); | |
642 DTRACE_PROBE1(hotspot_jni, ExceptionOccurred__return, ret); | |
643 return ret; | |
644 JNI_END | |
645 | |
646 | |
647 JNI_ENTRY_NO_PRESERVE(void, jni_ExceptionDescribe(JNIEnv *env)) | |
648 JNIWrapper("ExceptionDescribe"); | |
649 DTRACE_PROBE1(hotspot_jni, ExceptionDescribe__entry, env); | |
650 if (thread->has_pending_exception()) { | |
651 Handle ex(thread, thread->pending_exception()); | |
652 thread->clear_pending_exception(); | |
1142 | 653 if (ex->is_a(SystemDictionary::ThreadDeath_klass())) { |
0 | 654 // Don't print anything if we are being killed. |
655 } else { | |
656 jio_fprintf(defaultStream::error_stream(), "Exception "); | |
657 if (thread != NULL && thread->threadObj() != NULL) { | |
658 ResourceMark rm(THREAD); | |
659 jio_fprintf(defaultStream::error_stream(), | |
660 "in thread \"%s\" ", thread->get_thread_name()); | |
661 } | |
1142 | 662 if (ex->is_a(SystemDictionary::Throwable_klass())) { |
0 | 663 JavaValue result(T_VOID); |
664 JavaCalls::call_virtual(&result, | |
665 ex, | |
666 KlassHandle(THREAD, | |
1142 | 667 SystemDictionary::Throwable_klass()), |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
668 vmSymbols::printStackTrace_name(), |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
669 vmSymbols::void_method_signature(), |
0 | 670 THREAD); |
671 // If an exception is thrown in the call it gets thrown away. Not much | |
672 // we can do with it. The native code that calls this, does not check | |
673 // for the exception - hence, it might still be in the thread when DestroyVM gets | |
674 // called, potentially causing a few asserts to trigger - since no pending exception | |
675 // is expected. | |
676 CLEAR_PENDING_EXCEPTION; | |
677 } else { | |
678 ResourceMark rm(THREAD); | |
679 jio_fprintf(defaultStream::error_stream(), | |
680 ". Uncaught exception of type %s.", | |
681 Klass::cast(ex->klass())->external_name()); | |
682 } | |
683 } | |
684 } | |
685 DTRACE_PROBE(hotspot_jni, ExceptionDescribe__return); | |
686 JNI_END | |
687 | |
688 | |
689 JNI_QUICK_ENTRY(void, jni_ExceptionClear(JNIEnv *env)) | |
690 JNIWrapper("ExceptionClear"); | |
691 DTRACE_PROBE1(hotspot_jni, ExceptionClear__entry, env); | |
692 | |
693 // The jni code might be using this API to clear java thrown exception. | |
694 // So just mark jvmti thread exception state as exception caught. | |
695 JvmtiThreadState *state = JavaThread::current()->jvmti_thread_state(); | |
696 if (state != NULL && state->is_exception_detected()) { | |
697 state->set_exception_caught(); | |
698 } | |
699 thread->clear_pending_exception(); | |
700 DTRACE_PROBE(hotspot_jni, ExceptionClear__return); | |
701 JNI_END | |
702 | |
703 | |
704 JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg)) | |
705 JNIWrapper("FatalError"); | |
706 DTRACE_PROBE2(hotspot_jni, FatalError__entry, env, msg); | |
707 tty->print_cr("FATAL ERROR in native method: %s", msg); | |
708 thread->print_stack(); | |
227
8d852b81e775
6694099: Hotspot vm_exit_out_of_memory should dump core
poonam
parents:
113
diff
changeset
|
709 os::abort(); // Dump core and abort |
0 | 710 JNI_END |
711 | |
712 | |
713 JNI_ENTRY(jint, jni_PushLocalFrame(JNIEnv *env, jint capacity)) | |
714 JNIWrapper("PushLocalFrame"); | |
715 DTRACE_PROBE2(hotspot_jni, PushLocalFrame__entry, env, capacity); | |
716 //%note jni_11 | |
717 if (capacity < 0 && capacity > MAX_REASONABLE_LOCAL_CAPACITY) { | |
718 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR); | |
719 return JNI_ERR; | |
720 } | |
721 JNIHandleBlock* old_handles = thread->active_handles(); | |
722 JNIHandleBlock* new_handles = JNIHandleBlock::allocate_block(thread); | |
723 assert(new_handles != NULL, "should not be NULL"); | |
724 new_handles->set_pop_frame_link(old_handles); | |
725 thread->set_active_handles(new_handles); | |
726 jint ret = JNI_OK; | |
727 DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, ret); | |
728 return ret; | |
729 JNI_END | |
730 | |
731 | |
732 JNI_ENTRY(jobject, jni_PopLocalFrame(JNIEnv *env, jobject result)) | |
733 JNIWrapper("PopLocalFrame"); | |
734 DTRACE_PROBE2(hotspot_jni, PopLocalFrame__entry, env, result); | |
735 //%note jni_11 | |
736 Handle result_handle(thread, JNIHandles::resolve(result)); | |
737 JNIHandleBlock* old_handles = thread->active_handles(); | |
738 JNIHandleBlock* new_handles = old_handles->pop_frame_link(); | |
739 if (new_handles != NULL) { | |
740 // As a sanity check we only release the handle blocks if the pop_frame_link is not NULL. | |
741 // This way code will still work if PopLocalFrame is called without a corresponding | |
742 // PushLocalFrame call. Note that we set the pop_frame_link to NULL explicitly, otherwise | |
743 // the release_block call will release the blocks. | |
744 thread->set_active_handles(new_handles); | |
745 old_handles->set_pop_frame_link(NULL); // clear link we won't release new_handles below | |
746 JNIHandleBlock::release_block(old_handles, thread); // may block | |
747 result = JNIHandles::make_local(thread, result_handle()); | |
748 } | |
749 DTRACE_PROBE1(hotspot_jni, PopLocalFrame__return, result); | |
750 return result; | |
751 JNI_END | |
752 | |
753 | |
754 JNI_ENTRY(jobject, jni_NewGlobalRef(JNIEnv *env, jobject ref)) | |
755 JNIWrapper("NewGlobalRef"); | |
756 DTRACE_PROBE2(hotspot_jni, NewGlobalRef__entry, env, ref); | |
757 Handle ref_handle(thread, JNIHandles::resolve(ref)); | |
758 jobject ret = JNIHandles::make_global(ref_handle); | |
759 DTRACE_PROBE1(hotspot_jni, NewGlobalRef__return, ret); | |
760 return ret; | |
761 JNI_END | |
762 | |
763 // Must be JNI_ENTRY (with HandleMark) | |
764 JNI_ENTRY_NO_PRESERVE(void, jni_DeleteGlobalRef(JNIEnv *env, jobject ref)) | |
765 JNIWrapper("DeleteGlobalRef"); | |
766 DTRACE_PROBE2(hotspot_jni, DeleteGlobalRef__entry, env, ref); | |
767 JNIHandles::destroy_global(ref); | |
768 DTRACE_PROBE(hotspot_jni, DeleteGlobalRef__return); | |
769 JNI_END | |
770 | |
771 JNI_QUICK_ENTRY(void, jni_DeleteLocalRef(JNIEnv *env, jobject obj)) | |
772 JNIWrapper("DeleteLocalRef"); | |
773 DTRACE_PROBE2(hotspot_jni, DeleteLocalRef__entry, env, obj); | |
774 JNIHandles::destroy_local(obj); | |
775 DTRACE_PROBE(hotspot_jni, DeleteLocalRef__return); | |
776 JNI_END | |
777 | |
778 JNI_QUICK_ENTRY(jboolean, jni_IsSameObject(JNIEnv *env, jobject r1, jobject r2)) | |
779 JNIWrapper("IsSameObject"); | |
780 DTRACE_PROBE3(hotspot_jni, IsSameObject__entry, env, r1, r2); | |
781 oop a = JNIHandles::resolve(r1); | |
782 oop b = JNIHandles::resolve(r2); | |
783 jboolean ret = (a == b) ? JNI_TRUE : JNI_FALSE; | |
784 DTRACE_PROBE1(hotspot_jni, IsSameObject__return, ret); | |
785 return ret; | |
786 JNI_END | |
787 | |
788 | |
789 JNI_ENTRY(jobject, jni_NewLocalRef(JNIEnv *env, jobject ref)) | |
790 JNIWrapper("NewLocalRef"); | |
791 DTRACE_PROBE2(hotspot_jni, NewLocalRef__entry, env, ref); | |
792 jobject ret = JNIHandles::make_local(env, JNIHandles::resolve(ref)); | |
793 DTRACE_PROBE1(hotspot_jni, NewLocalRef__return, ret); | |
794 return ret; | |
795 JNI_END | |
796 | |
797 JNI_LEAF(jint, jni_EnsureLocalCapacity(JNIEnv *env, jint capacity)) | |
798 JNIWrapper("EnsureLocalCapacity"); | |
799 DTRACE_PROBE2(hotspot_jni, EnsureLocalCapacity__entry, env, capacity); | |
800 jint ret; | |
801 if (capacity >= 0 && capacity <= MAX_REASONABLE_LOCAL_CAPACITY) { | |
802 ret = JNI_OK; | |
803 } else { | |
804 ret = JNI_ERR; | |
805 } | |
806 DTRACE_PROBE1(hotspot_jni, EnsureLocalCapacity__return, ret); | |
807 return ret; | |
808 JNI_END | |
809 | |
810 // Return the Handle Type | |
811 JNI_LEAF(jobjectRefType, jni_GetObjectRefType(JNIEnv *env, jobject obj)) | |
812 JNIWrapper("GetObjectRefType"); | |
813 DTRACE_PROBE2(hotspot_jni, GetObjectRefType__entry, env, obj); | |
814 jobjectRefType ret; | |
815 if (JNIHandles::is_local_handle(thread, obj) || | |
816 JNIHandles::is_frame_handle(thread, obj)) | |
817 ret = JNILocalRefType; | |
818 else if (JNIHandles::is_global_handle(obj)) | |
819 ret = JNIGlobalRefType; | |
820 else if (JNIHandles::is_weak_global_handle(obj)) | |
821 ret = JNIWeakGlobalRefType; | |
822 else | |
823 ret = JNIInvalidRefType; | |
824 DTRACE_PROBE1(hotspot_jni, GetObjectRefType__return, ret); | |
825 return ret; | |
826 JNI_END | |
827 | |
828 | |
829 class JNI_ArgumentPusher : public SignatureIterator { | |
830 protected: | |
831 JavaCallArguments* _arguments; | |
832 | |
833 virtual void get_bool () = 0; | |
834 virtual void get_char () = 0; | |
835 virtual void get_short () = 0; | |
836 virtual void get_byte () = 0; | |
837 virtual void get_int () = 0; | |
838 virtual void get_long () = 0; | |
839 virtual void get_float () = 0; | |
840 virtual void get_double () = 0; | |
841 virtual void get_object () = 0; | |
842 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
843 JNI_ArgumentPusher(Symbol* signature) : SignatureIterator(signature) { |
0 | 844 this->_return_type = T_ILLEGAL; |
845 _arguments = NULL; | |
846 } | |
847 | |
848 public: | |
849 virtual void iterate( uint64_t fingerprint ) = 0; | |
850 | |
851 void set_java_argument_object(JavaCallArguments *arguments) { _arguments = arguments; } | |
852 | |
853 inline void do_bool() { if (!is_return_type()) get_bool(); } | |
854 inline void do_char() { if (!is_return_type()) get_char(); } | |
855 inline void do_short() { if (!is_return_type()) get_short(); } | |
856 inline void do_byte() { if (!is_return_type()) get_byte(); } | |
857 inline void do_int() { if (!is_return_type()) get_int(); } | |
858 inline void do_long() { if (!is_return_type()) get_long(); } | |
859 inline void do_float() { if (!is_return_type()) get_float(); } | |
860 inline void do_double() { if (!is_return_type()) get_double(); } | |
861 inline void do_object(int begin, int end) { if (!is_return_type()) get_object(); } | |
862 inline void do_array(int begin, int end) { if (!is_return_type()) get_object(); } // do_array uses get_object -- there is no get_array | |
863 inline void do_void() { } | |
864 | |
865 JavaCallArguments* arguments() { return _arguments; } | |
866 void push_receiver(Handle h) { _arguments->push_oop(h); } | |
867 }; | |
868 | |
869 | |
870 class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { | |
871 protected: | |
872 va_list _ap; | |
873 | |
874 inline void get_bool() { _arguments->push_int(va_arg(_ap, jint)); } // bool is coerced to int when using va_arg | |
875 inline void get_char() { _arguments->push_int(va_arg(_ap, jint)); } // char is coerced to int when using va_arg | |
876 inline void get_short() { _arguments->push_int(va_arg(_ap, jint)); } // short is coerced to int when using va_arg | |
877 inline void get_byte() { _arguments->push_int(va_arg(_ap, jint)); } // byte is coerced to int when using va_arg | |
878 inline void get_int() { _arguments->push_int(va_arg(_ap, jint)); } | |
879 | |
880 // each of these paths is exercized by the various jck Call[Static,Nonvirtual,][Void,Int,..]Method[A,V,] tests | |
881 | |
882 inline void get_long() { _arguments->push_long(va_arg(_ap, jlong)); } | |
883 inline void get_float() { _arguments->push_float((jfloat)va_arg(_ap, jdouble)); } // float is coerced to double w/ va_arg | |
884 inline void get_double() { _arguments->push_double(va_arg(_ap, jdouble)); } | |
885 inline void get_object() { jobject l = va_arg(_ap, jobject); | |
886 _arguments->push_oop(Handle((oop *)l, false)); } | |
887 | |
888 inline void set_ap(va_list rap) { | |
889 #ifdef va_copy | |
890 va_copy(_ap, rap); | |
891 #elif defined (__va_copy) | |
892 __va_copy(_ap, rap); | |
893 #else | |
894 _ap = rap; | |
895 #endif | |
896 } | |
897 | |
898 public: | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
899 JNI_ArgumentPusherVaArg(Symbol* signature, va_list rap) |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
900 : JNI_ArgumentPusher(signature) { |
0 | 901 set_ap(rap); |
902 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
903 JNI_ArgumentPusherVaArg(jmethodID method_id, va_list rap) |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
904 : JNI_ArgumentPusher(JNIHandles::resolve_jmethod_id(method_id)->signature()) { |
0 | 905 set_ap(rap); |
906 } | |
907 | |
908 // Optimized path if we have the bitvector form of signature | |
909 void iterate( uint64_t fingerprint ) { | |
910 if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate();// Must be too many arguments | |
911 else { | |
912 _return_type = (BasicType)((fingerprint >> static_feature_size) & | |
913 result_feature_mask); | |
914 | |
915 assert(fingerprint, "Fingerprint should not be 0"); | |
916 fingerprint = fingerprint >> (static_feature_size + result_feature_size); | |
917 while ( 1 ) { | |
918 switch ( fingerprint & parameter_feature_mask ) { | |
919 case bool_parm: | |
920 case char_parm: | |
921 case short_parm: | |
922 case byte_parm: | |
923 case int_parm: | |
924 get_int(); | |
925 break; | |
926 case obj_parm: | |
927 get_object(); | |
928 break; | |
929 case long_parm: | |
930 get_long(); | |
931 break; | |
932 case float_parm: | |
933 get_float(); | |
934 break; | |
935 case double_parm: | |
936 get_double(); | |
937 break; | |
938 case done_parm: | |
939 return; | |
940 break; | |
941 default: | |
942 ShouldNotReachHere(); | |
943 break; | |
944 } | |
945 fingerprint >>= parameter_feature_size; | |
946 } | |
947 } | |
948 } | |
949 }; | |
950 | |
951 | |
952 class JNI_ArgumentPusherArray : public JNI_ArgumentPusher { | |
953 protected: | |
954 const jvalue *_ap; | |
955 | |
956 inline void get_bool() { _arguments->push_int((jint)(_ap++)->z); } | |
957 inline void get_char() { _arguments->push_int((jint)(_ap++)->c); } | |
958 inline void get_short() { _arguments->push_int((jint)(_ap++)->s); } | |
959 inline void get_byte() { _arguments->push_int((jint)(_ap++)->b); } | |
960 inline void get_int() { _arguments->push_int((jint)(_ap++)->i); } | |
961 | |
962 inline void get_long() { _arguments->push_long((_ap++)->j); } | |
963 inline void get_float() { _arguments->push_float((_ap++)->f); } | |
964 inline void get_double() { _arguments->push_double((_ap++)->d);} | |
965 inline void get_object() { _arguments->push_oop(Handle((oop *)(_ap++)->l, false)); } | |
966 | |
967 inline void set_ap(const jvalue *rap) { _ap = rap; } | |
968 | |
969 public: | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
970 JNI_ArgumentPusherArray(Symbol* signature, const jvalue *rap) |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
971 : JNI_ArgumentPusher(signature) { |
0 | 972 set_ap(rap); |
973 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
974 JNI_ArgumentPusherArray(jmethodID method_id, const jvalue *rap) |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
975 : JNI_ArgumentPusher(JNIHandles::resolve_jmethod_id(method_id)->signature()) { |
0 | 976 set_ap(rap); |
977 } | |
978 | |
979 // Optimized path if we have the bitvector form of signature | |
980 void iterate( uint64_t fingerprint ) { | |
981 if ( fingerprint == UCONST64(-1) ) SignatureIterator::iterate(); // Must be too many arguments | |
982 else { | |
983 _return_type = (BasicType)((fingerprint >> static_feature_size) & | |
984 result_feature_mask); | |
985 assert(fingerprint, "Fingerprint should not be 0"); | |
986 fingerprint = fingerprint >> (static_feature_size + result_feature_size); | |
987 while ( 1 ) { | |
988 switch ( fingerprint & parameter_feature_mask ) { | |
989 case bool_parm: | |
990 get_bool(); | |
991 break; | |
992 case char_parm: | |
993 get_char(); | |
994 break; | |
995 case short_parm: | |
996 get_short(); | |
997 break; | |
998 case byte_parm: | |
999 get_byte(); | |
1000 break; | |
1001 case int_parm: | |
1002 get_int(); | |
1003 break; | |
1004 case obj_parm: | |
1005 get_object(); | |
1006 break; | |
1007 case long_parm: | |
1008 get_long(); | |
1009 break; | |
1010 case float_parm: | |
1011 get_float(); | |
1012 break; | |
1013 case double_parm: | |
1014 get_double(); | |
1015 break; | |
1016 case done_parm: | |
1017 return; | |
1018 break; | |
1019 default: | |
1020 ShouldNotReachHere(); | |
1021 break; | |
1022 } | |
1023 fingerprint >>= parameter_feature_size; | |
1024 } | |
1025 } | |
1026 } | |
1027 }; | |
1028 | |
1029 | |
1030 enum JNICallType { | |
1031 JNI_STATIC, | |
1032 JNI_VIRTUAL, | |
1033 JNI_NONVIRTUAL | |
1034 }; | |
1035 | |
1036 static methodHandle jni_resolve_interface_call(Handle recv, methodHandle method, TRAPS) { | |
1037 assert(!method.is_null() , "method should not be null"); | |
1038 | |
1039 KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc) | |
1040 if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass()); | |
1041 KlassHandle spec_klass (THREAD, method->method_holder()); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1042 Symbol* name = method->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1043 Symbol* signature = method->signature(); |
0 | 1044 CallInfo info; |
1045 LinkResolver::resolve_interface_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle())); | |
1046 return info.selected_method(); | |
1047 } | |
1048 | |
1049 static methodHandle jni_resolve_virtual_call(Handle recv, methodHandle method, TRAPS) { | |
1050 assert(!method.is_null() , "method should not be null"); | |
1051 | |
1052 KlassHandle recv_klass; // Default to NULL (use of ?: can confuse gcc) | |
1053 if (recv.not_null()) recv_klass = KlassHandle(THREAD, recv->klass()); | |
1054 KlassHandle spec_klass (THREAD, method->method_holder()); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1055 Symbol* name = method->name(); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1056 Symbol* signature = method->signature(); |
0 | 1057 CallInfo info; |
1058 LinkResolver::resolve_virtual_call(info, recv, recv_klass, spec_klass, name, signature, KlassHandle(), false, true, CHECK_(methodHandle())); | |
1059 return info.selected_method(); | |
1060 } | |
1061 | |
1062 | |
1063 | |
1064 static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { | |
1065 methodHandle method(THREAD, JNIHandles::resolve_jmethod_id(method_id)); | |
1066 | |
1067 // Create object to hold arguments for the JavaCall, and associate it with | |
1068 // the jni parser | |
1069 ResourceMark rm(THREAD); | |
1070 int number_of_parameters = method->size_of_parameters(); | |
1071 JavaCallArguments java_args(number_of_parameters); | |
1072 args->set_java_argument_object(&java_args); | |
1073 | |
1074 assert(method->is_static(), "method should be static"); | |
1075 | |
1076 // Fill out JavaCallArguments object | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1077 args->iterate( Fingerprinter(method).fingerprint() ); |
0 | 1078 // Initialize result type |
1079 result->set_type(args->get_ret_type()); | |
1080 | |
1081 // Invoke the method. Result is returned as oop. | |
1082 JavaCalls::call(result, method, &java_args, CHECK); | |
1083 | |
1084 // Convert result | |
1085 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { | |
1086 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); | |
1087 } | |
1088 } | |
1089 | |
1090 | |
1091 static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { | |
1092 oop recv = JNIHandles::resolve(receiver); | |
1093 if (recv == NULL) { | |
1094 THROW(vmSymbols::java_lang_NullPointerException()); | |
1095 } | |
1096 Handle h_recv(THREAD, recv); | |
1097 | |
1098 int number_of_parameters; | |
1099 methodOop selected_method; | |
1100 { | |
1101 methodOop m = JNIHandles::resolve_jmethod_id(method_id); | |
1102 number_of_parameters = m->size_of_parameters(); | |
1103 klassOop holder = m->method_holder(); | |
1104 if (!(Klass::cast(holder))->is_interface()) { | |
1105 // non-interface call -- for that little speed boost, don't handlize | |
1106 debug_only(No_Safepoint_Verifier nosafepoint;) | |
1107 if (call_type == JNI_VIRTUAL) { | |
1108 // jni_GetMethodID makes sure class is linked and initialized | |
1109 // so m should have a valid vtable index. | |
1110 int vtbl_index = m->vtable_index(); | |
1111 if (vtbl_index != methodOopDesc::nonvirtual_vtable_index) { | |
1112 klassOop k = h_recv->klass(); | |
1113 // k might be an arrayKlassOop but all vtables start at | |
1114 // the same place. The cast is to avoid virtual call and assertion. | |
1115 instanceKlass *ik = (instanceKlass*)k->klass_part(); | |
1116 selected_method = ik->method_at_vtable(vtbl_index); | |
1117 } else { | |
1118 // final method | |
1119 selected_method = m; | |
1120 } | |
1121 } else { | |
1122 // JNI_NONVIRTUAL call | |
1123 selected_method = m; | |
1124 } | |
1125 } else { | |
1126 // interface call | |
1127 KlassHandle h_holder(THREAD, holder); | |
1128 | |
1129 int itbl_index = m->cached_itable_index(); | |
1130 if (itbl_index == -1) { | |
1131 itbl_index = klassItable::compute_itable_index(m); | |
1132 m->set_cached_itable_index(itbl_index); | |
1133 // the above may have grabbed a lock, 'm' and anything non-handlized can't be used again | |
1134 } | |
1135 klassOop k = h_recv->klass(); | |
1136 selected_method = instanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); | |
1137 } | |
1138 } | |
1139 | |
1140 methodHandle method(THREAD, selected_method); | |
1141 | |
1142 // Create object to hold arguments for the JavaCall, and associate it with | |
1143 // the jni parser | |
1144 ResourceMark rm(THREAD); | |
1145 JavaCallArguments java_args(number_of_parameters); | |
1146 args->set_java_argument_object(&java_args); | |
1147 | |
1148 // handle arguments | |
1149 assert(!method->is_static(), "method should not be static"); | |
1150 args->push_receiver(h_recv); // Push jobject handle | |
1151 | |
1152 // Fill out JavaCallArguments object | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1153 args->iterate( Fingerprinter(method).fingerprint() ); |
0 | 1154 // Initialize result type |
1155 result->set_type(args->get_ret_type()); | |
1156 | |
1157 // Invoke the method. Result is returned as oop. | |
1158 JavaCalls::call(result, method, &java_args, CHECK); | |
1159 | |
1160 // Convert result | |
1161 if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { | |
1162 result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); | |
1163 } | |
1164 } | |
1165 | |
1166 | |
1167 static instanceOop alloc_object(jclass clazz, TRAPS) { | |
1168 KlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
1169 Klass::cast(k())->check_valid_for_instantiation(false, CHECK_NULL); | |
1170 instanceKlass::cast(k())->initialize(CHECK_NULL); | |
1171 instanceOop ih = instanceKlass::cast(k())->allocate_instance(THREAD); | |
1172 return ih; | |
1173 } | |
1174 | |
1175 DT_RETURN_MARK_DECL(AllocObject, jobject); | |
1176 | |
1177 JNI_ENTRY(jobject, jni_AllocObject(JNIEnv *env, jclass clazz)) | |
1178 JNIWrapper("AllocObject"); | |
1179 | |
1180 DTRACE_PROBE2(hotspot_jni, AllocObject__entry, env, clazz); | |
1181 jobject ret = NULL; | |
1182 DT_RETURN_MARK(AllocObject, jobject, (const jobject&)ret); | |
1183 | |
1184 instanceOop i = alloc_object(clazz, CHECK_NULL); | |
1185 ret = JNIHandles::make_local(env, i); | |
1186 return ret; | |
1187 JNI_END | |
1188 | |
1189 DT_RETURN_MARK_DECL(NewObjectA, jobject); | |
1190 | |
1191 JNI_ENTRY(jobject, jni_NewObjectA(JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args)) | |
1192 JNIWrapper("NewObjectA"); | |
1193 DTRACE_PROBE3(hotspot_jni, NewObjectA__entry, env, clazz, methodID); | |
1194 jobject obj = NULL; | |
1195 DT_RETURN_MARK(NewObjectA, jobject, (const jobject)obj); | |
1196 | |
1197 instanceOop i = alloc_object(clazz, CHECK_NULL); | |
1198 obj = JNIHandles::make_local(env, i); | |
1199 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1200 JNI_ArgumentPusherArray ap(methodID, args); |
0 | 1201 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); |
1202 return obj; | |
1203 JNI_END | |
1204 | |
1205 DT_RETURN_MARK_DECL(NewObjectV, jobject); | |
1206 | |
1207 JNI_ENTRY(jobject, jni_NewObjectV(JNIEnv *env, jclass clazz, jmethodID methodID, va_list args)) | |
1208 JNIWrapper("NewObjectV"); | |
1209 DTRACE_PROBE3(hotspot_jni, NewObjectV__entry, env, clazz, methodID); | |
1210 jobject obj = NULL; | |
1211 DT_RETURN_MARK(NewObjectV, jobject, (const jobject&)obj); | |
1212 | |
1213 instanceOop i = alloc_object(clazz, CHECK_NULL); | |
1214 obj = JNIHandles::make_local(env, i); | |
1215 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1216 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1217 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); |
1218 return obj; | |
1219 JNI_END | |
1220 | |
1221 DT_RETURN_MARK_DECL(NewObject, jobject); | |
1222 | |
1223 JNI_ENTRY(jobject, jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)) | |
1224 JNIWrapper("NewObject"); | |
1225 DTRACE_PROBE3(hotspot_jni, NewObject__entry, env, clazz, methodID); | |
1226 jobject obj = NULL; | |
1227 DT_RETURN_MARK(NewObject, jobject, (const jobject&)obj); | |
1228 | |
1229 instanceOop i = alloc_object(clazz, CHECK_NULL); | |
1230 obj = JNIHandles::make_local(env, i); | |
1231 va_list args; | |
1232 va_start(args, methodID); | |
1233 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1234 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1235 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_NULL); |
1236 va_end(args); | |
1237 return obj; | |
1238 JNI_END | |
1239 | |
1240 | |
1241 JNI_ENTRY(jclass, jni_GetObjectClass(JNIEnv *env, jobject obj)) | |
1242 JNIWrapper("GetObjectClass"); | |
1243 DTRACE_PROBE2(hotspot_jni, GetObjectClass__entry, env, obj); | |
1244 klassOop k = JNIHandles::resolve_non_null(obj)->klass(); | |
1245 jclass ret = | |
1246 (jclass) JNIHandles::make_local(env, Klass::cast(k)->java_mirror()); | |
1247 DTRACE_PROBE1(hotspot_jni, GetObjectClass__return, ret); | |
1248 return ret; | |
1249 JNI_END | |
1250 | |
1251 JNI_QUICK_ENTRY(jboolean, jni_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)) | |
1252 JNIWrapper("IsInstanceOf"); | |
1253 DTRACE_PROBE3(hotspot_jni, IsInstanceOf__entry, env, obj, clazz); | |
1254 jboolean ret = JNI_TRUE; | |
1255 if (obj != NULL) { | |
1256 ret = JNI_FALSE; | |
1257 klassOop k = java_lang_Class::as_klassOop( | |
1258 JNIHandles::resolve_non_null(clazz)); | |
1259 if (k != NULL) { | |
1260 ret = JNIHandles::resolve_non_null(obj)->is_a(k) ? JNI_TRUE : JNI_FALSE; | |
1261 } | |
1262 } | |
1263 DTRACE_PROBE1(hotspot_jni, IsInstanceOf__return, ret); | |
1264 return ret; | |
1265 JNI_END | |
1266 | |
1267 | |
1268 static jmethodID get_method_id(JNIEnv *env, jclass clazz, const char *name_str, | |
1269 const char *sig, bool is_static, TRAPS) { | |
1270 // %%%% This code should probably just call into a method in the LinkResolver | |
1271 // | |
1272 // The class should have been loaded (we have an instance of the class | |
1273 // passed in) so the method and signature should already be in the symbol | |
1274 // table. If they're not there, the method doesn't exist. | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1275 const char *name_to_probe = (name_str == NULL) |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1276 ? vmSymbols::object_initializer_name()->as_C_string() |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1277 : name_str; |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1278 TempNewSymbol name = SymbolTable::probe(name_to_probe, (int)strlen(name_to_probe)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1279 TempNewSymbol signature = SymbolTable::probe(sig, (int)strlen(sig)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1280 |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1281 if (name == NULL || signature == NULL) { |
0 | 1282 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); |
1283 } | |
1284 | |
1285 // Throw a NoSuchMethodError exception if we have an instance of a | |
1286 // primitive java.lang.Class | |
1287 if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(clazz))) { | |
1288 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); | |
1289 } | |
1290 | |
1291 KlassHandle klass(THREAD, | |
1292 java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
1293 | |
1294 // Make sure class is linked and initialized before handing id's out to | |
1295 // methodOops. | |
1296 Klass::cast(klass())->initialize(CHECK_NULL); | |
1297 | |
1298 methodOop m; | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1299 if (name == vmSymbols::object_initializer_name() || |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1300 name == vmSymbols::class_initializer_name()) { |
0 | 1301 // Never search superclasses for constructors |
1302 if (klass->oop_is_instance()) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1303 m = instanceKlass::cast(klass())->find_method(name, signature); |
0 | 1304 } else { |
1305 m = NULL; | |
1306 } | |
1307 } else { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1308 m = klass->lookup_method(name, signature); |
0 | 1309 // Look up interfaces |
1310 if (m == NULL && klass->oop_is_instance()) { | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1311 m = instanceKlass::cast(klass())->lookup_method_in_all_interfaces(name, |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1312 signature); |
0 | 1313 } |
1314 } | |
1315 if (m == NULL || (m->is_static() != is_static)) { | |
1316 THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(), name_str); | |
1317 } | |
1318 return m->jmethod_id(); | |
1319 } | |
1320 | |
1321 | |
1322 JNI_ENTRY(jmethodID, jni_GetMethodID(JNIEnv *env, jclass clazz, | |
1323 const char *name, const char *sig)) | |
1324 JNIWrapper("GetMethodID"); | |
1325 DTRACE_PROBE4(hotspot_jni, GetMethodID__entry, env, clazz, name, sig); | |
1326 jmethodID ret = get_method_id(env, clazz, name, sig, false, thread); | |
1327 DTRACE_PROBE1(hotspot_jni, GetMethodID__return, ret); | |
1328 return ret; | |
1329 JNI_END | |
1330 | |
1331 | |
1332 JNI_ENTRY(jmethodID, jni_GetStaticMethodID(JNIEnv *env, jclass clazz, | |
1333 const char *name, const char *sig)) | |
1334 JNIWrapper("GetStaticMethodID"); | |
1335 DTRACE_PROBE4(hotspot_jni, GetStaticMethodID__entry, env, clazz, name, sig); | |
1336 jmethodID ret = get_method_id(env, clazz, name, sig, true, thread); | |
1337 DTRACE_PROBE1(hotspot_jni, GetStaticMethodID__return, ret); | |
1338 return ret; | |
1339 JNI_END | |
1340 | |
1341 | |
1342 | |
1343 // | |
1344 // Calling Methods | |
1345 // | |
1346 | |
1347 | |
1348 #define DEFINE_CALLMETHOD(ResultType, Result, Tag) \ | |
1349 \ | |
1350 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##Method, ResultType);\ | |
1351 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodV, ResultType);\ | |
1352 DT_RETURN_MARK_DECL_FOR(Result, Call##Result##MethodA, ResultType);\ | |
1353 \ | |
1354 JNI_ENTRY(ResultType, \ | |
1355 jni_Call##Result##Method(JNIEnv *env, jobject obj, jmethodID methodID, ...)) \ | |
1356 JNIWrapper("Call" XSTR(Result) "Method"); \ | |
1357 \ | |
1358 DTRACE_PROBE3(hotspot_jni, Call##Result##Method__entry, env, obj, methodID);\ | |
1359 ResultType ret = 0;\ | |
1360 DT_RETURN_MARK_FOR(Result, Call##Result##Method, ResultType, \ | |
1361 (const ResultType&)ret);\ | |
1362 \ | |
1363 va_list args; \ | |
1364 va_start(args, methodID); \ | |
1365 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1366 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1367 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ |
1368 va_end(args); \ | |
1369 ret = jvalue.get_##ResultType(); \ | |
1370 return ret;\ | |
1371 JNI_END \ | |
1372 \ | |
1373 \ | |
1374 JNI_ENTRY(ResultType, \ | |
1375 jni_Call##Result##MethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) \ | |
1376 JNIWrapper("Call" XSTR(Result) "MethodV"); \ | |
1377 \ | |
1378 DTRACE_PROBE3(hotspot_jni, Call##Result##MethodV__entry, env, obj, methodID);\ | |
1379 ResultType ret = 0;\ | |
1380 DT_RETURN_MARK_FOR(Result, Call##Result##MethodV, ResultType, \ | |
1381 (const ResultType&)ret);\ | |
1382 \ | |
1383 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1384 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1385 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ |
1386 ret = jvalue.get_##ResultType(); \ | |
1387 return ret;\ | |
1388 JNI_END \ | |
1389 \ | |
1390 \ | |
1391 JNI_ENTRY(ResultType, \ | |
1392 jni_Call##Result##MethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) \ | |
1393 JNIWrapper("Call" XSTR(Result) "MethodA"); \ | |
1394 DTRACE_PROBE3(hotspot_jni, Call##Result##MethodA__entry, env, obj, methodID);\ | |
1395 ResultType ret = 0;\ | |
1396 DT_RETURN_MARK_FOR(Result, Call##Result##MethodA, ResultType, \ | |
1397 (const ResultType&)ret);\ | |
1398 \ | |
1399 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1400 JNI_ArgumentPusherArray ap(methodID, args); \ |
0 | 1401 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK_0); \ |
1402 ret = jvalue.get_##ResultType(); \ | |
1403 return ret;\ | |
1404 JNI_END | |
1405 | |
1406 // the runtime type of subword integral basic types is integer | |
1407 DEFINE_CALLMETHOD(jboolean, Boolean, T_BOOLEAN) | |
1408 DEFINE_CALLMETHOD(jbyte, Byte, T_BYTE) | |
1409 DEFINE_CALLMETHOD(jchar, Char, T_CHAR) | |
1410 DEFINE_CALLMETHOD(jshort, Short, T_SHORT) | |
1411 | |
1412 DEFINE_CALLMETHOD(jobject, Object, T_OBJECT) | |
1413 DEFINE_CALLMETHOD(jint, Int, T_INT) | |
1414 DEFINE_CALLMETHOD(jlong, Long, T_LONG) | |
1415 DEFINE_CALLMETHOD(jfloat, Float, T_FLOAT) | |
1416 DEFINE_CALLMETHOD(jdouble, Double, T_DOUBLE) | |
1417 | |
1418 DT_VOID_RETURN_MARK_DECL(CallVoidMethod); | |
1419 DT_VOID_RETURN_MARK_DECL(CallVoidMethodV); | |
1420 DT_VOID_RETURN_MARK_DECL(CallVoidMethodA); | |
1421 | |
1422 JNI_ENTRY(void, jni_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)) | |
1423 JNIWrapper("CallVoidMethod"); | |
1424 DTRACE_PROBE3(hotspot_jni, CallVoidMethod__entry, env, obj, methodID); | |
1425 DT_VOID_RETURN_MARK(CallVoidMethod); | |
1426 | |
1427 va_list args; | |
1428 va_start(args, methodID); | |
1429 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1430 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1431 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); |
1432 va_end(args); | |
1433 JNI_END | |
1434 | |
1435 | |
1436 JNI_ENTRY(void, jni_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID, va_list args)) | |
1437 JNIWrapper("CallVoidMethodV"); | |
1438 DTRACE_PROBE3(hotspot_jni, CallVoidMethodV__entry, env, obj, methodID); | |
1439 DT_VOID_RETURN_MARK(CallVoidMethodV); | |
1440 | |
1441 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1442 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1443 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); |
1444 JNI_END | |
1445 | |
1446 | |
1447 JNI_ENTRY(void, jni_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args)) | |
1448 JNIWrapper("CallVoidMethodA"); | |
1449 DTRACE_PROBE3(hotspot_jni, CallVoidMethodA__entry, env, obj, methodID); | |
1450 DT_VOID_RETURN_MARK(CallVoidMethodA); | |
1451 | |
1452 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1453 JNI_ArgumentPusherArray ap(methodID, args); |
0 | 1454 jni_invoke_nonstatic(env, &jvalue, obj, JNI_VIRTUAL, methodID, &ap, CHECK); |
1455 JNI_END | |
1456 | |
1457 | |
1458 #define DEFINE_CALLNONVIRTUALMETHOD(ResultType, Result, Tag) \ | |
1459 \ | |
1460 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##Method, ResultType);\ | |
1461 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodV, ResultType);\ | |
1462 DT_RETURN_MARK_DECL_FOR(Result, CallNonvirtual##Result##MethodA, ResultType);\ | |
1463 \ | |
1464 JNI_ENTRY(ResultType, \ | |
1465 jni_CallNonvirtual##Result##Method(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) \ | |
1466 JNIWrapper("CallNonvitual" XSTR(Result) "Method"); \ | |
1467 \ | |
1468 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##Method__entry, env, obj, cls, methodID);\ | |
1469 ResultType ret;\ | |
1470 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##Method, ResultType, \ | |
1471 (const ResultType&)ret);\ | |
1472 \ | |
1473 va_list args; \ | |
1474 va_start(args, methodID); \ | |
1475 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1476 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1477 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ |
1478 va_end(args); \ | |
1479 ret = jvalue.get_##ResultType(); \ | |
1480 return ret;\ | |
1481 JNI_END \ | |
1482 \ | |
1483 JNI_ENTRY(ResultType, \ | |
1484 jni_CallNonvirtual##Result##MethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) \ | |
1485 JNIWrapper("CallNonvitual" XSTR(Result) "#MethodV"); \ | |
1486 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodV__entry, env, obj, cls, methodID);\ | |
1487 ResultType ret;\ | |
1488 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodV, ResultType, \ | |
1489 (const ResultType&)ret);\ | |
1490 \ | |
1491 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1492 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1493 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ |
1494 ret = jvalue.get_##ResultType(); \ | |
1495 return ret;\ | |
1496 JNI_END \ | |
1497 \ | |
1498 JNI_ENTRY(ResultType, \ | |
1499 jni_CallNonvirtual##Result##MethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) \ | |
1500 JNIWrapper("CallNonvitual" XSTR(Result) "MethodA"); \ | |
1501 DTRACE_PROBE4(hotspot_jni, CallNonvirtual##Result##MethodA__entry, env, obj, cls, methodID);\ | |
1502 ResultType ret;\ | |
1503 DT_RETURN_MARK_FOR(Result, CallNonvirtual##Result##MethodA, ResultType, \ | |
1504 (const ResultType&)ret);\ | |
1505 \ | |
1506 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1507 JNI_ArgumentPusherArray ap(methodID, args); \ |
0 | 1508 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK_0); \ |
1509 ret = jvalue.get_##ResultType(); \ | |
1510 return ret;\ | |
1511 JNI_END | |
1512 | |
1513 // the runtime type of subword integral basic types is integer | |
1514 DEFINE_CALLNONVIRTUALMETHOD(jboolean, Boolean, T_BOOLEAN) | |
1515 DEFINE_CALLNONVIRTUALMETHOD(jbyte, Byte, T_BYTE) | |
1516 DEFINE_CALLNONVIRTUALMETHOD(jchar, Char, T_CHAR) | |
1517 DEFINE_CALLNONVIRTUALMETHOD(jshort, Short, T_SHORT) | |
1518 | |
1519 DEFINE_CALLNONVIRTUALMETHOD(jobject, Object, T_OBJECT) | |
1520 DEFINE_CALLNONVIRTUALMETHOD(jint, Int, T_INT) | |
1521 DEFINE_CALLNONVIRTUALMETHOD(jlong, Long, T_LONG) | |
1522 DEFINE_CALLNONVIRTUALMETHOD(jfloat, Float, T_FLOAT) | |
1523 DEFINE_CALLNONVIRTUALMETHOD(jdouble, Double, T_DOUBLE) | |
1524 | |
1525 | |
1526 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethod); | |
1527 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodV); | |
1528 DT_VOID_RETURN_MARK_DECL(CallNonvirtualVoidMethodA); | |
1529 | |
1530 JNI_ENTRY(void, jni_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, ...)) | |
1531 JNIWrapper("CallNonvirtualVoidMethod"); | |
1532 | |
1533 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethod__entry, | |
1534 env, obj, cls, methodID); | |
1535 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethod); | |
1536 | |
1537 va_list args; | |
1538 va_start(args, methodID); | |
1539 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1540 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1541 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); |
1542 va_end(args); | |
1543 JNI_END | |
1544 | |
1545 | |
1546 JNI_ENTRY(void, jni_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, va_list args)) | |
1547 JNIWrapper("CallNonvirtualVoidMethodV"); | |
1548 | |
1549 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodV__entry, | |
1550 env, obj, cls, methodID); | |
1551 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodV); | |
1552 | |
1553 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1554 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1555 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); |
1556 JNI_END | |
1557 | |
1558 | |
1559 JNI_ENTRY(void, jni_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass cls, jmethodID methodID, const jvalue *args)) | |
1560 JNIWrapper("CallNonvirtualVoidMethodA"); | |
1561 DTRACE_PROBE4(hotspot_jni, CallNonvirtualVoidMethodA__entry, | |
1562 env, obj, cls, methodID); | |
1563 DT_VOID_RETURN_MARK(CallNonvirtualVoidMethodA); | |
1564 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1565 JNI_ArgumentPusherArray ap(methodID, args); |
0 | 1566 jni_invoke_nonstatic(env, &jvalue, obj, JNI_NONVIRTUAL, methodID, &ap, CHECK); |
1567 JNI_END | |
1568 | |
1569 | |
1570 #define DEFINE_CALLSTATICMETHOD(ResultType, Result, Tag) \ | |
1571 \ | |
1572 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##Method, ResultType);\ | |
1573 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodV, ResultType);\ | |
1574 DT_RETURN_MARK_DECL_FOR(Result, CallStatic##Result##MethodA, ResultType);\ | |
1575 \ | |
1576 JNI_ENTRY(ResultType, \ | |
1577 jni_CallStatic##Result##Method(JNIEnv *env, jclass cls, jmethodID methodID, ...)) \ | |
1578 JNIWrapper("CallStatic" XSTR(Result) "Method"); \ | |
1579 \ | |
1580 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##Method__entry, env, cls, methodID);\ | |
1581 ResultType ret = 0;\ | |
1582 DT_RETURN_MARK_FOR(Result, CallStatic##Result##Method, ResultType, \ | |
1583 (const ResultType&)ret);\ | |
1584 \ | |
1585 va_list args; \ | |
1586 va_start(args, methodID); \ | |
1587 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1588 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1589 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ |
1590 va_end(args); \ | |
1591 ret = jvalue.get_##ResultType(); \ | |
1592 return ret;\ | |
1593 JNI_END \ | |
1594 \ | |
1595 JNI_ENTRY(ResultType, \ | |
1596 jni_CallStatic##Result##MethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) \ | |
1597 JNIWrapper("CallStatic" XSTR(Result) "MethodV"); \ | |
1598 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodV__entry, env, cls, methodID);\ | |
1599 ResultType ret = 0;\ | |
1600 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodV, ResultType, \ | |
1601 (const ResultType&)ret);\ | |
1602 \ | |
1603 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1604 JNI_ArgumentPusherVaArg ap(methodID, args); \ |
0 | 1605 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ |
1606 ret = jvalue.get_##ResultType(); \ | |
1607 return ret;\ | |
1608 JNI_END \ | |
1609 \ | |
1610 JNI_ENTRY(ResultType, \ | |
1611 jni_CallStatic##Result##MethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) \ | |
1612 JNIWrapper("CallStatic" XSTR(Result) "MethodA"); \ | |
1613 DTRACE_PROBE3(hotspot_jni, CallStatic##Result##MethodA__entry, env, cls, methodID);\ | |
1614 ResultType ret = 0;\ | |
1615 DT_RETURN_MARK_FOR(Result, CallStatic##Result##MethodA, ResultType, \ | |
1616 (const ResultType&)ret);\ | |
1617 \ | |
1618 JavaValue jvalue(Tag); \ | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1619 JNI_ArgumentPusherArray ap(methodID, args); \ |
0 | 1620 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK_0); \ |
1621 ret = jvalue.get_##ResultType(); \ | |
1622 return ret;\ | |
1623 JNI_END | |
1624 | |
1625 // the runtime type of subword integral basic types is integer | |
1626 DEFINE_CALLSTATICMETHOD(jboolean, Boolean, T_BOOLEAN) | |
1627 DEFINE_CALLSTATICMETHOD(jbyte, Byte, T_BYTE) | |
1628 DEFINE_CALLSTATICMETHOD(jchar, Char, T_CHAR) | |
1629 DEFINE_CALLSTATICMETHOD(jshort, Short, T_SHORT) | |
1630 | |
1631 DEFINE_CALLSTATICMETHOD(jobject, Object, T_OBJECT) | |
1632 DEFINE_CALLSTATICMETHOD(jint, Int, T_INT) | |
1633 DEFINE_CALLSTATICMETHOD(jlong, Long, T_LONG) | |
1634 DEFINE_CALLSTATICMETHOD(jfloat, Float, T_FLOAT) | |
1635 DEFINE_CALLSTATICMETHOD(jdouble, Double, T_DOUBLE) | |
1636 | |
1637 | |
1638 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethod); | |
1639 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodV); | |
1640 DT_VOID_RETURN_MARK_DECL(CallStaticVoidMethodA); | |
1641 | |
1642 JNI_ENTRY(void, jni_CallStaticVoidMethod(JNIEnv *env, jclass cls, jmethodID methodID, ...)) | |
1643 JNIWrapper("CallStaticVoidMethod"); | |
1644 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethod__entry, env, cls, methodID); | |
1645 DT_VOID_RETURN_MARK(CallStaticVoidMethod); | |
1646 | |
1647 va_list args; | |
1648 va_start(args, methodID); | |
1649 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1650 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1651 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); |
1652 va_end(args); | |
1653 JNI_END | |
1654 | |
1655 | |
1656 JNI_ENTRY(void, jni_CallStaticVoidMethodV(JNIEnv *env, jclass cls, jmethodID methodID, va_list args)) | |
1657 JNIWrapper("CallStaticVoidMethodV"); | |
1658 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodV__entry, env, cls, methodID); | |
1659 DT_VOID_RETURN_MARK(CallStaticVoidMethodV); | |
1660 | |
1661 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1662 JNI_ArgumentPusherVaArg ap(methodID, args); |
0 | 1663 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); |
1664 JNI_END | |
1665 | |
1666 | |
1667 JNI_ENTRY(void, jni_CallStaticVoidMethodA(JNIEnv *env, jclass cls, jmethodID methodID, const jvalue *args)) | |
1668 JNIWrapper("CallStaticVoidMethodA"); | |
1669 DTRACE_PROBE3(hotspot_jni, CallStaticVoidMethodA__entry, env, cls, methodID); | |
1670 DT_VOID_RETURN_MARK(CallStaticVoidMethodA); | |
1671 | |
1672 JavaValue jvalue(T_VOID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1673 JNI_ArgumentPusherArray ap(methodID, args); |
0 | 1674 jni_invoke_static(env, &jvalue, NULL, JNI_STATIC, methodID, &ap, CHECK); |
1675 JNI_END | |
1676 | |
1677 | |
1678 // | |
1679 // Accessing Fields | |
1680 // | |
1681 | |
1682 | |
1683 DT_RETURN_MARK_DECL(GetFieldID, jfieldID); | |
1684 | |
1685 JNI_ENTRY(jfieldID, jni_GetFieldID(JNIEnv *env, jclass clazz, | |
1686 const char *name, const char *sig)) | |
1687 JNIWrapper("GetFieldID"); | |
1688 DTRACE_PROBE4(hotspot_jni, GetFieldID__entry, env, clazz, name, sig); | |
1689 jfieldID ret = 0; | |
1690 DT_RETURN_MARK(GetFieldID, jfieldID, (const jfieldID&)ret); | |
1691 | |
1692 // The class should have been loaded (we have an instance of the class | |
1693 // passed in) so the field and signature should already be in the symbol | |
1694 // table. If they're not there, the field doesn't exist. | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1695 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1696 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1697 if (fieldname == NULL || signame == NULL) { |
0 | 1698 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); |
1699 } | |
1700 KlassHandle k(THREAD, | |
1701 java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
1702 // Make sure class is initialized before handing id's out to fields | |
1703 Klass::cast(k())->initialize(CHECK_NULL); | |
1704 | |
1705 fieldDescriptor fd; | |
1706 if (!Klass::cast(k())->oop_is_instance() || | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1707 !instanceKlass::cast(k())->find_field(fieldname, signame, false, &fd)) { |
0 | 1708 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); |
1709 } | |
1710 | |
1711 // A jfieldID for a non-static field is simply the offset of the field within the instanceOop | |
1712 // It may also have hash bits for k, if VerifyJNIFields is turned on. | |
1713 ret = jfieldIDWorkaround::to_instance_jfieldID(k(), fd.offset()); | |
1714 return ret; | |
1715 JNI_END | |
1716 | |
1717 | |
1718 JNI_ENTRY(jobject, jni_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)) | |
1719 JNIWrapper("GetObjectField"); | |
1720 DTRACE_PROBE3(hotspot_jni, GetObjectField__entry, env, obj, fieldID); | |
1721 oop o = JNIHandles::resolve_non_null(obj); | |
1722 klassOop k = o->klass(); | |
1723 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | |
1724 // Keep JVMTI addition small and only check enabled flag here. | |
1725 // jni_GetField_probe() assumes that is okay to create handles. | |
1726 if (JvmtiExport::should_post_field_access()) { | |
1727 o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); | |
1728 } | |
1729 jobject ret = JNIHandles::make_local(env, o->obj_field(offset)); | |
3249
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1730 #ifndef SERIALGC |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1731 // If G1 is enabled and we are accessing the value of the referent |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1732 // field in a reference object then we need to register a non-null |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1733 // referent with the SATB barrier. |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1734 if (UseG1GC) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1735 bool needs_barrier = false; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1736 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1737 if (ret != NULL && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1738 offset == java_lang_ref_Reference::referent_offset && |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1739 instanceKlass::cast(k)->reference_type() != REF_NONE) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1740 assert(instanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1741 needs_barrier = true; |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1742 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1743 |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1744 if (needs_barrier) { |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1745 oop referent = JNIHandles::resolve(ret); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1746 G1SATBCardTableModRefBS::enqueue(referent); |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1747 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1748 } |
e1162778c1c8
7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
johnc
parents:
2376
diff
changeset
|
1749 #endif // SERIALGC |
0 | 1750 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); |
1751 return ret; | |
1752 JNI_END | |
1753 | |
1754 | |
1755 #define DEFINE_GETFIELD(Return,Fieldname,Result) \ | |
1756 \ | |
1757 DT_RETURN_MARK_DECL_FOR(Result, Get##Result##Field, Return);\ | |
1758 \ | |
1759 JNI_QUICK_ENTRY(Return, jni_Get##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID)) \ | |
1760 JNIWrapper("Get" XSTR(Result) "Field"); \ | |
1761 \ | |
1762 DTRACE_PROBE3(hotspot_jni, Get##Result##Field__entry, env, obj, fieldID);\ | |
1763 Return ret = 0;\ | |
1764 DT_RETURN_MARK_FOR(Result, Get##Result##Field, Return, (const Return&)ret);\ | |
1765 \ | |
1766 oop o = JNIHandles::resolve_non_null(obj); \ | |
1767 klassOop k = o->klass(); \ | |
1768 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ | |
1769 /* Keep JVMTI addition small and only check enabled flag here. */ \ | |
1770 /* jni_GetField_probe_nh() assumes that is not okay to create handles */ \ | |
1771 /* and creates a ResetNoHandleMark. */ \ | |
1772 if (JvmtiExport::should_post_field_access()) { \ | |
1773 o = JvmtiExport::jni_GetField_probe_nh(thread, obj, o, k, fieldID, false); \ | |
1774 } \ | |
1775 ret = o->Fieldname##_field(offset); \ | |
1776 return ret; \ | |
1777 JNI_END | |
1778 | |
1779 DEFINE_GETFIELD(jboolean, bool, Boolean) | |
1780 DEFINE_GETFIELD(jbyte, byte, Byte) | |
1781 DEFINE_GETFIELD(jchar, char, Char) | |
1782 DEFINE_GETFIELD(jshort, short, Short) | |
1783 DEFINE_GETFIELD(jint, int, Int) | |
1784 DEFINE_GETFIELD(jlong, long, Long) | |
1785 DEFINE_GETFIELD(jfloat, float, Float) | |
1786 DEFINE_GETFIELD(jdouble, double, Double) | |
1787 | |
1788 address jni_GetBooleanField_addr() { | |
1789 return (address)jni_GetBooleanField; | |
1790 } | |
1791 address jni_GetByteField_addr() { | |
1792 return (address)jni_GetByteField; | |
1793 } | |
1794 address jni_GetCharField_addr() { | |
1795 return (address)jni_GetCharField; | |
1796 } | |
1797 address jni_GetShortField_addr() { | |
1798 return (address)jni_GetShortField; | |
1799 } | |
1800 address jni_GetIntField_addr() { | |
1801 return (address)jni_GetIntField; | |
1802 } | |
1803 address jni_GetLongField_addr() { | |
1804 return (address)jni_GetLongField; | |
1805 } | |
1806 address jni_GetFloatField_addr() { | |
1807 return (address)jni_GetFloatField; | |
1808 } | |
1809 address jni_GetDoubleField_addr() { | |
1810 return (address)jni_GetDoubleField; | |
1811 } | |
1812 | |
1813 JNI_QUICK_ENTRY(void, jni_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID, jobject value)) | |
1814 JNIWrapper("SetObjectField"); | |
1815 DTRACE_PROBE4(hotspot_jni, SetObjectField__entry, env, obj, fieldID, value); | |
1816 oop o = JNIHandles::resolve_non_null(obj); | |
1817 klassOop k = o->klass(); | |
1818 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | |
1819 // Keep JVMTI addition small and only check enabled flag here. | |
1820 // jni_SetField_probe_nh() assumes that is not okay to create handles | |
1821 // and creates a ResetNoHandleMark. | |
1822 if (JvmtiExport::should_post_field_modification()) { | |
1823 jvalue field_value; | |
1824 field_value.l = value; | |
1825 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, 'L', (jvalue *)&field_value); | |
1826 } | |
1827 o->obj_field_put(offset, JNIHandles::resolve(value)); | |
1828 DTRACE_PROBE(hotspot_jni, SetObjectField__return); | |
1829 JNI_END | |
1830 | |
1831 #define DEFINE_SETFIELD(Argument,Fieldname,Result,SigType,unionType) \ | |
1832 \ | |
1833 JNI_QUICK_ENTRY(void, jni_Set##Result##Field(JNIEnv *env, jobject obj, jfieldID fieldID, Argument value)) \ | |
1834 JNIWrapper("Set" XSTR(Result) "Field"); \ | |
1835 \ | |
1836 HS_DTRACE_PROBE_CDECL_N(hotspot_jni, Set##Result##Field__entry, \ | |
1837 ( JNIEnv*, jobject, jfieldID FP_SELECT_##Result(COMMA Argument,/*empty*/) ) ); \ | |
1838 HS_DTRACE_PROBE_N(hotspot_jni, Set##Result##Field__entry, \ | |
1839 ( env, obj, fieldID FP_SELECT_##Result(COMMA value,/*empty*/) ) ); \ | |
1840 \ | |
1841 oop o = JNIHandles::resolve_non_null(obj); \ | |
1842 klassOop k = o->klass(); \ | |
1843 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); \ | |
1844 /* Keep JVMTI addition small and only check enabled flag here. */ \ | |
1845 /* jni_SetField_probe_nh() assumes that is not okay to create handles */ \ | |
1846 /* and creates a ResetNoHandleMark. */ \ | |
1847 if (JvmtiExport::should_post_field_modification()) { \ | |
1848 jvalue field_value; \ | |
1849 field_value.unionType = value; \ | |
1850 o = JvmtiExport::jni_SetField_probe_nh(thread, obj, o, k, fieldID, false, SigType, (jvalue *)&field_value); \ | |
1851 } \ | |
1852 o->Fieldname##_field_put(offset, value); \ | |
1853 DTRACE_PROBE(hotspot_jni, Set##Result##Field__return);\ | |
1854 JNI_END | |
1855 | |
1856 DEFINE_SETFIELD(jboolean, bool, Boolean, 'Z', z) | |
1857 DEFINE_SETFIELD(jbyte, byte, Byte, 'B', b) | |
1858 DEFINE_SETFIELD(jchar, char, Char, 'C', c) | |
1859 DEFINE_SETFIELD(jshort, short, Short, 'S', s) | |
1860 DEFINE_SETFIELD(jint, int, Int, 'I', i) | |
1861 DEFINE_SETFIELD(jlong, long, Long, 'J', j) | |
1862 DEFINE_SETFIELD(jfloat, float, Float, 'F', f) | |
1863 DEFINE_SETFIELD(jdouble, double, Double, 'D', d) | |
1864 | |
1865 DT_RETURN_MARK_DECL(ToReflectedField, jobject); | |
1866 | |
1867 JNI_ENTRY(jobject, jni_ToReflectedField(JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic)) | |
1868 JNIWrapper("ToReflectedField"); | |
1869 DTRACE_PROBE4(hotspot_jni, ToReflectedField__entry, | |
1870 env, cls, fieldID, isStatic); | |
1871 jobject ret = NULL; | |
1872 DT_RETURN_MARK(ToReflectedField, jobject, (const jobject&)ret); | |
1873 | |
1874 fieldDescriptor fd; | |
1875 bool found = false; | |
1876 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(cls)); | |
1877 | |
1878 assert(jfieldIDWorkaround::is_static_jfieldID(fieldID) == (isStatic != 0), "invalid fieldID"); | |
1879 | |
1880 if (isStatic) { | |
1881 // Static field. The fieldID a JNIid specifying the field holder and the offset within the klassOop. | |
1882 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | |
1883 assert(id->is_static_field_id(), "invalid static field id"); | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
1884 found = id->find_local_field(&fd); |
0 | 1885 } else { |
1886 // Non-static field. The fieldID is really the offset of the field within the instanceOop. | |
1887 int offset = jfieldIDWorkaround::from_instance_jfieldID(k, fieldID); | |
1888 found = instanceKlass::cast(k)->find_field_from_offset(offset, false, &fd); | |
1889 } | |
1890 assert(found, "bad fieldID passed into jni_ToReflectedField"); | |
1891 oop reflected = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL); | |
1892 ret = JNIHandles::make_local(env, reflected); | |
1893 return ret; | |
1894 JNI_END | |
1895 | |
1896 | |
1897 // | |
1898 // Accessing Static Fields | |
1899 // | |
1900 DT_RETURN_MARK_DECL(GetStaticFieldID, jfieldID); | |
1901 | |
1902 JNI_ENTRY(jfieldID, jni_GetStaticFieldID(JNIEnv *env, jclass clazz, | |
1903 const char *name, const char *sig)) | |
1904 JNIWrapper("GetStaticFieldID"); | |
1905 DTRACE_PROBE4(hotspot_jni, GetStaticFieldID__entry, env, clazz, name, sig); | |
1906 jfieldID ret = NULL; | |
1907 DT_RETURN_MARK(GetStaticFieldID, jfieldID, (const jfieldID&)ret); | |
1908 | |
1909 // The class should have been loaded (we have an instance of the class | |
1910 // passed in) so the field and signature should already be in the symbol | |
1911 // table. If they're not there, the field doesn't exist. | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1912 TempNewSymbol fieldname = SymbolTable::probe(name, (int)strlen(name)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1913 TempNewSymbol signame = SymbolTable::probe(sig, (int)strlen(sig)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1914 if (fieldname == NULL || signame == NULL) { |
0 | 1915 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); |
1916 } | |
1917 KlassHandle k(THREAD, | |
1918 java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
1919 // Make sure class is initialized before handing id's out to static fields | |
1920 Klass::cast(k())->initialize(CHECK_NULL); | |
1921 | |
1922 fieldDescriptor fd; | |
1923 if (!Klass::cast(k())->oop_is_instance() || | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
1924 !instanceKlass::cast(k())->find_field(fieldname, signame, true, &fd)) { |
0 | 1925 THROW_MSG_0(vmSymbols::java_lang_NoSuchFieldError(), (char*) name); |
1926 } | |
1927 | |
1928 // A jfieldID for a static field is a JNIid specifying the field holder and the offset within the klassOop | |
1929 JNIid* id = instanceKlass::cast(fd.field_holder())->jni_id_for(fd.offset()); | |
1930 debug_only(id->set_is_static_field_id();) | |
1931 | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
1932 debug_only(id->verify(fd.field_holder())); |
0 | 1933 |
1934 ret = jfieldIDWorkaround::to_static_jfieldID(id); | |
1935 return ret; | |
1936 JNI_END | |
1937 | |
1938 | |
1939 JNI_ENTRY(jobject, jni_GetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID)) | |
1940 JNIWrapper("GetStaticObjectField"); | |
1941 DTRACE_PROBE3(hotspot_jni, GetStaticObjectField__entry, env, clazz, fieldID); | |
1942 #ifndef JNICHECK_KERNEL | |
1943 DEBUG_ONLY(klassOop param_k = jniCheck::validate_class(thread, clazz);) | |
1944 #endif // JNICHECK_KERNEL | |
1945 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | |
1946 assert(id->is_static_field_id(), "invalid static field id"); | |
1947 // Keep JVMTI addition small and only check enabled flag here. | |
1948 // jni_GetField_probe() assumes that is okay to create handles. | |
1949 if (JvmtiExport::should_post_field_access()) { | |
1950 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); | |
1951 } | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
1952 jobject ret = JNIHandles::make_local(id->holder()->java_mirror()->obj_field(id->offset())); |
0 | 1953 DTRACE_PROBE1(hotspot_jni, GetStaticObjectField__return, ret); |
1954 return ret; | |
1955 JNI_END | |
1956 | |
1957 #define DEFINE_GETSTATICFIELD(Return,Fieldname,Result) \ | |
1958 \ | |
1959 DT_RETURN_MARK_DECL_FOR(Result, GetStatic##Result##Field, Return);\ | |
1960 \ | |
1961 JNI_ENTRY(Return, jni_GetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID)) \ | |
1962 JNIWrapper("GetStatic" XSTR(Result) "Field"); \ | |
1963 DTRACE_PROBE3(hotspot_jni, GetStatic##Result##Field__entry, env, clazz, fieldID);\ | |
1964 Return ret = 0;\ | |
1965 DT_RETURN_MARK_FOR(Result, GetStatic##Result##Field, Return, \ | |
1966 (const Return&)ret);\ | |
1967 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ | |
1968 assert(id->is_static_field_id(), "invalid static field id"); \ | |
1969 /* Keep JVMTI addition small and only check enabled flag here. */ \ | |
1970 /* jni_GetField_probe() assumes that is okay to create handles. */ \ | |
1971 if (JvmtiExport::should_post_field_access()) { \ | |
1972 JvmtiExport::jni_GetField_probe(thread, NULL, NULL, id->holder(), fieldID, true); \ | |
1973 } \ | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
1974 ret = id->holder()->java_mirror()-> Fieldname##_field (id->offset()); \ |
0 | 1975 return ret;\ |
1976 JNI_END | |
1977 | |
1978 DEFINE_GETSTATICFIELD(jboolean, bool, Boolean) | |
1979 DEFINE_GETSTATICFIELD(jbyte, byte, Byte) | |
1980 DEFINE_GETSTATICFIELD(jchar, char, Char) | |
1981 DEFINE_GETSTATICFIELD(jshort, short, Short) | |
1982 DEFINE_GETSTATICFIELD(jint, int, Int) | |
1983 DEFINE_GETSTATICFIELD(jlong, long, Long) | |
1984 DEFINE_GETSTATICFIELD(jfloat, float, Float) | |
1985 DEFINE_GETSTATICFIELD(jdouble, double, Double) | |
1986 | |
1987 | |
1988 JNI_ENTRY(void, jni_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value)) | |
1989 JNIWrapper("SetStaticObjectField"); | |
1990 DTRACE_PROBE4(hotspot_jni, SetStaticObjectField__entry, env, clazz, fieldID, value); | |
1991 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); | |
1992 assert(id->is_static_field_id(), "invalid static field id"); | |
1993 // Keep JVMTI addition small and only check enabled flag here. | |
1994 // jni_SetField_probe() assumes that is okay to create handles. | |
1995 if (JvmtiExport::should_post_field_modification()) { | |
1996 jvalue field_value; | |
1997 field_value.l = value; | |
1998 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, 'L', (jvalue *)&field_value); | |
1999 } | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
2000 id->holder()->java_mirror()->obj_field_put(id->offset(), JNIHandles::resolve(value)); |
0 | 2001 DTRACE_PROBE(hotspot_jni, SetStaticObjectField__return); |
2002 JNI_END | |
2003 | |
2004 | |
2005 #define DEFINE_SETSTATICFIELD(Argument,Fieldname,Result,SigType,unionType) \ | |
2006 \ | |
2007 JNI_ENTRY(void, jni_SetStatic##Result##Field(JNIEnv *env, jclass clazz, jfieldID fieldID, Argument value)) \ | |
2008 JNIWrapper("SetStatic" XSTR(Result) "Field"); \ | |
2009 HS_DTRACE_PROBE_CDECL_N(hotspot_jni, SetStatic##Result##Field__entry,\ | |
2010 ( JNIEnv*, jclass, jfieldID FP_SELECT_##Result(COMMA Argument,/*empty*/) ) ); \ | |
2011 HS_DTRACE_PROBE_N(hotspot_jni, SetStatic##Result##Field__entry, \ | |
2012 ( env, clazz, fieldID FP_SELECT_##Result(COMMA value,/*empty*/) ) ); \ | |
2013 \ | |
2014 JNIid* id = jfieldIDWorkaround::from_static_jfieldID(fieldID); \ | |
2015 assert(id->is_static_field_id(), "invalid static field id"); \ | |
2016 /* Keep JVMTI addition small and only check enabled flag here. */ \ | |
2017 /* jni_SetField_probe() assumes that is okay to create handles. */ \ | |
2018 if (JvmtiExport::should_post_field_modification()) { \ | |
2019 jvalue field_value; \ | |
2020 field_value.unionType = value; \ | |
2021 JvmtiExport::jni_SetField_probe(thread, NULL, NULL, id->holder(), fieldID, true, SigType, (jvalue *)&field_value); \ | |
2022 } \ | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
2177
diff
changeset
|
2023 id->holder()->java_mirror()-> Fieldname##_field_put (id->offset(), value); \ |
0 | 2024 DTRACE_PROBE(hotspot_jni, SetStatic##Result##Field__return);\ |
2025 JNI_END | |
2026 | |
2027 DEFINE_SETSTATICFIELD(jboolean, bool, Boolean, 'Z', z) | |
2028 DEFINE_SETSTATICFIELD(jbyte, byte, Byte, 'B', b) | |
2029 DEFINE_SETSTATICFIELD(jchar, char, Char, 'C', c) | |
2030 DEFINE_SETSTATICFIELD(jshort, short, Short, 'S', s) | |
2031 DEFINE_SETSTATICFIELD(jint, int, Int, 'I', i) | |
2032 DEFINE_SETSTATICFIELD(jlong, long, Long, 'J', j) | |
2033 DEFINE_SETSTATICFIELD(jfloat, float, Float, 'F', f) | |
2034 DEFINE_SETSTATICFIELD(jdouble, double, Double, 'D', d) | |
2035 | |
2036 | |
2037 // | |
2038 // String Operations | |
2039 // | |
2040 | |
2041 // Unicode Interface | |
2042 | |
2043 DT_RETURN_MARK_DECL(NewString, jstring); | |
2044 | |
2045 JNI_ENTRY(jstring, jni_NewString(JNIEnv *env, const jchar *unicodeChars, jsize len)) | |
2046 JNIWrapper("NewString"); | |
2047 DTRACE_PROBE3(hotspot_jni, NewString__entry, env, unicodeChars, len); | |
2048 jstring ret = NULL; | |
2049 DT_RETURN_MARK(NewString, jstring, (const jstring&)ret); | |
2050 oop string=java_lang_String::create_oop_from_unicode((jchar*) unicodeChars, len, CHECK_NULL); | |
2051 ret = (jstring) JNIHandles::make_local(env, string); | |
2052 return ret; | |
2053 JNI_END | |
2054 | |
2055 | |
2056 JNI_QUICK_ENTRY(jsize, jni_GetStringLength(JNIEnv *env, jstring string)) | |
2057 JNIWrapper("GetStringLength"); | |
2058 DTRACE_PROBE2(hotspot_jni, GetStringLength__entry, env, string); | |
2059 jsize ret = java_lang_String::length(JNIHandles::resolve_non_null(string)); | |
2060 DTRACE_PROBE1(hotspot_jni, GetStringLength__return, ret); | |
2061 return ret; | |
2062 JNI_END | |
2063 | |
2064 | |
2065 JNI_QUICK_ENTRY(const jchar*, jni_GetStringChars( | |
2066 JNIEnv *env, jstring string, jboolean *isCopy)) | |
2067 JNIWrapper("GetStringChars"); | |
2068 DTRACE_PROBE3(hotspot_jni, GetStringChars__entry, env, string, isCopy); | |
2069 //%note jni_5 | |
2070 if (isCopy != NULL) { | |
2071 *isCopy = JNI_TRUE; | |
2072 } | |
2073 oop s = JNIHandles::resolve_non_null(string); | |
2074 int s_len = java_lang_String::length(s); | |
2075 typeArrayOop s_value = java_lang_String::value(s); | |
2076 int s_offset = java_lang_String::offset(s); | |
2077 jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len + 1); // add one for zero termination | |
2078 if (s_len > 0) { | |
2079 memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len); | |
2080 } | |
2081 buf[s_len] = 0; | |
2082 DTRACE_PROBE1(hotspot_jni, GetStringChars__return, buf); | |
2083 return buf; | |
2084 JNI_END | |
2085 | |
2086 | |
2087 JNI_QUICK_ENTRY(void, jni_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)) | |
2088 JNIWrapper("ReleaseStringChars"); | |
2089 DTRACE_PROBE3(hotspot_jni, ReleaseStringChars__entry, env, str, chars); | |
2090 //%note jni_6 | |
2091 if (chars != NULL) { | |
2092 // Since String objects are supposed to be immutable, don't copy any | |
2093 // new data back. A bad user will have to go after the char array. | |
2094 FreeHeap((void*) chars); | |
2095 } | |
2096 DTRACE_PROBE(hotspot_jni, ReleaseStringChars__return); | |
2097 JNI_END | |
2098 | |
2099 | |
2100 // UTF Interface | |
2101 | |
2102 DT_RETURN_MARK_DECL(NewStringUTF, jstring); | |
2103 | |
2104 JNI_ENTRY(jstring, jni_NewStringUTF(JNIEnv *env, const char *bytes)) | |
2105 JNIWrapper("NewStringUTF"); | |
2106 DTRACE_PROBE2(hotspot_jni, NewStringUTF__entry, env, bytes); | |
2107 jstring ret; | |
2108 DT_RETURN_MARK(NewStringUTF, jstring, (const jstring&)ret); | |
2109 | |
2110 oop result = java_lang_String::create_oop_from_str((char*) bytes, CHECK_NULL); | |
2111 ret = (jstring) JNIHandles::make_local(env, result); | |
2112 return ret; | |
2113 JNI_END | |
2114 | |
2115 | |
2116 JNI_ENTRY(jsize, jni_GetStringUTFLength(JNIEnv *env, jstring string)) | |
2117 JNIWrapper("GetStringUTFLength"); | |
2118 DTRACE_PROBE2(hotspot_jni, GetStringUTFLength__entry, env, string); | |
2119 jsize ret = java_lang_String::utf8_length(JNIHandles::resolve_non_null(string)); | |
2120 DTRACE_PROBE1(hotspot_jni, GetStringUTFLength__return, ret); | |
2121 return ret; | |
2122 JNI_END | |
2123 | |
2124 | |
2125 JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)) | |
2126 JNIWrapper("GetStringUTFChars"); | |
2127 DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy); | |
1989
017cd8bce8a8
6539281: -Xcheck:jni should validate char* argument to ReleaseStringUTFChars
sla
parents:
1980
diff
changeset
|
2128 oop java_string = JNIHandles::resolve_non_null(string); |
017cd8bce8a8
6539281: -Xcheck:jni should validate char* argument to ReleaseStringUTFChars
sla
parents:
1980
diff
changeset
|
2129 size_t length = java_lang_String::utf8_length(java_string); |
017cd8bce8a8
6539281: -Xcheck:jni should validate char* argument to ReleaseStringUTFChars
sla
parents:
1980
diff
changeset
|
2130 char* result = AllocateHeap(length + 1, "GetStringUTFChars"); |
017cd8bce8a8
6539281: -Xcheck:jni should validate char* argument to ReleaseStringUTFChars
sla
parents:
1980
diff
changeset
|
2131 java_lang_String::as_utf8_string(java_string, result, (int) length + 1); |
0 | 2132 if (isCopy != NULL) *isCopy = JNI_TRUE; |
2133 DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result); | |
2134 return result; | |
2135 JNI_END | |
2136 | |
2137 | |
2138 JNI_LEAF(void, jni_ReleaseStringUTFChars(JNIEnv *env, jstring str, const char *chars)) | |
2139 JNIWrapper("ReleaseStringUTFChars"); | |
2140 DTRACE_PROBE3(hotspot_jni, ReleaseStringUTFChars__entry, env, str, chars); | |
2141 if (chars != NULL) { | |
2142 FreeHeap((char*) chars); | |
2143 } | |
2144 DTRACE_PROBE(hotspot_jni, ReleaseStringUTFChars__return); | |
2145 JNI_END | |
2146 | |
2147 | |
2148 JNI_QUICK_ENTRY(jsize, jni_GetArrayLength(JNIEnv *env, jarray array)) | |
2149 JNIWrapper("GetArrayLength"); | |
2150 DTRACE_PROBE2(hotspot_jni, GetArrayLength__entry, env, array); | |
2151 arrayOop a = arrayOop(JNIHandles::resolve_non_null(array)); | |
2152 assert(a->is_array(), "must be array"); | |
2153 jsize ret = a->length(); | |
2154 DTRACE_PROBE1(hotspot_jni, GetArrayLength__return, ret); | |
2155 return ret; | |
2156 JNI_END | |
2157 | |
2158 | |
2159 // | |
2160 // Object Array Operations | |
2161 // | |
2162 | |
2163 DT_RETURN_MARK_DECL(NewObjectArray, jobjectArray); | |
2164 | |
2165 JNI_ENTRY(jobjectArray, jni_NewObjectArray(JNIEnv *env, jsize length, jclass elementClass, jobject initialElement)) | |
2166 JNIWrapper("NewObjectArray"); | |
2167 DTRACE_PROBE4(hotspot_jni, NewObjectArray__entry, env, length, elementClass, initialElement); | |
2168 jobjectArray ret = NULL; | |
2169 DT_RETURN_MARK(NewObjectArray, jobjectArray, (const jobjectArray&)ret); | |
2170 KlassHandle ek(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(elementClass))); | |
2171 klassOop ako = Klass::cast(ek())->array_klass(CHECK_NULL); | |
2172 KlassHandle ak = KlassHandle(THREAD, ako); | |
2173 objArrayKlass::cast(ak())->initialize(CHECK_NULL); | |
2174 objArrayOop result = objArrayKlass::cast(ak())->allocate(length, CHECK_NULL); | |
2175 oop initial_value = JNIHandles::resolve(initialElement); | |
2176 if (initial_value != NULL) { // array already initialized with NULL | |
2177 for (int index = 0; index < length; index++) { | |
2178 result->obj_at_put(index, initial_value); | |
2179 } | |
2180 } | |
2181 ret = (jobjectArray) JNIHandles::make_local(env, result); | |
2182 return ret; | |
2183 JNI_END | |
2184 | |
2185 DT_RETURN_MARK_DECL(GetObjectArrayElement, jobject); | |
2186 | |
2187 JNI_ENTRY(jobject, jni_GetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index)) | |
2188 JNIWrapper("GetObjectArrayElement"); | |
2189 DTRACE_PROBE3(hotspot_jni, GetObjectArrayElement__entry, env, array, index); | |
2190 jobject ret = NULL; | |
2191 DT_RETURN_MARK(GetObjectArrayElement, jobject, (const jobject&)ret); | |
2192 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); | |
2193 if (a->is_within_bounds(index)) { | |
1034
08780c8a9f04
6893483: DTrace probe return values for a couple JNI methods are wrong
kamg
parents:
973
diff
changeset
|
2194 ret = JNIHandles::make_local(env, a->obj_at(index)); |
0 | 2195 return ret; |
2196 } else { | |
2197 char buf[jintAsStringSize]; | |
2198 sprintf(buf, "%d", index); | |
2199 THROW_MSG_0(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf); | |
2200 } | |
2201 JNI_END | |
2202 | |
2203 DT_VOID_RETURN_MARK_DECL(SetObjectArrayElement); | |
2204 | |
2205 JNI_ENTRY(void, jni_SetObjectArrayElement(JNIEnv *env, jobjectArray array, jsize index, jobject value)) | |
2206 JNIWrapper("SetObjectArrayElement"); | |
2207 DTRACE_PROBE4(hotspot_jni, SetObjectArrayElement__entry, env, array, index, value); | |
2208 DT_VOID_RETURN_MARK(SetObjectArrayElement); | |
2209 | |
2210 objArrayOop a = objArrayOop(JNIHandles::resolve_non_null(array)); | |
2211 oop v = JNIHandles::resolve(value); | |
2212 if (a->is_within_bounds(index)) { | |
2213 if (v == NULL || v->is_a(objArrayKlass::cast(a->klass())->element_klass())) { | |
2214 a->obj_at_put(index, v); | |
2215 } else { | |
2216 THROW(vmSymbols::java_lang_ArrayStoreException()); | |
2217 } | |
2218 } else { | |
2219 char buf[jintAsStringSize]; | |
2220 sprintf(buf, "%d", index); | |
2221 THROW_MSG(vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), buf); | |
2222 } | |
2223 JNI_END | |
2224 | |
2225 | |
2226 #define DEFINE_NEWSCALARARRAY(Return,Allocator,Result) \ | |
2227 \ | |
1034
08780c8a9f04
6893483: DTrace probe return values for a couple JNI methods are wrong
kamg
parents:
973
diff
changeset
|
2228 DT_RETURN_MARK_DECL(New##Result##Array, Return);\ |
0 | 2229 \ |
2230 JNI_ENTRY(Return, \ | |
2231 jni_New##Result##Array(JNIEnv *env, jsize len)) \ | |
2232 JNIWrapper("New" XSTR(Result) "Array"); \ | |
2233 DTRACE_PROBE2(hotspot_jni, New##Result##Array__entry, env, len);\ | |
2234 Return ret = NULL;\ | |
1034
08780c8a9f04
6893483: DTrace probe return values for a couple JNI methods are wrong
kamg
parents:
973
diff
changeset
|
2235 DT_RETURN_MARK(New##Result##Array, Return, (const Return&)ret);\ |
0 | 2236 \ |
2237 oop obj= oopFactory::Allocator(len, CHECK_0); \ | |
2238 ret = (Return) JNIHandles::make_local(env, obj); \ | |
2239 return ret;\ | |
2240 JNI_END | |
2241 | |
2242 DEFINE_NEWSCALARARRAY(jbooleanArray, new_boolArray, Boolean) | |
2243 DEFINE_NEWSCALARARRAY(jbyteArray, new_byteArray, Byte) | |
2244 DEFINE_NEWSCALARARRAY(jshortArray, new_shortArray, Short) | |
2245 DEFINE_NEWSCALARARRAY(jcharArray, new_charArray, Char) | |
2246 DEFINE_NEWSCALARARRAY(jintArray, new_intArray, Int) | |
2247 DEFINE_NEWSCALARARRAY(jlongArray, new_longArray, Long) | |
2248 DEFINE_NEWSCALARARRAY(jfloatArray, new_singleArray, Float) | |
2249 DEFINE_NEWSCALARARRAY(jdoubleArray, new_doubleArray, Double) | |
2250 | |
2251 | |
2252 // Return an address which will fault if the caller writes to it. | |
2253 | |
2254 static char* get_bad_address() { | |
2255 static char* bad_address = NULL; | |
2256 if (bad_address == NULL) { | |
2257 size_t size = os::vm_allocation_granularity(); | |
2258 bad_address = os::reserve_memory(size); | |
2259 if (bad_address != NULL) { | |
477
24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents:
237
diff
changeset
|
2260 os::protect_memory(bad_address, size, os::MEM_PROT_READ, |
24fda36852ce
6727377: VM stack guard pages on Windows should PAGE_READWRITE not PAGE_EXECUTE_READWRITE
coleenp
parents:
237
diff
changeset
|
2261 /*is_committed*/false); |
0 | 2262 } |
2263 } | |
2264 return bad_address; | |
2265 } | |
2266 | |
2267 | |
2268 #define DEFINE_GETSCALARARRAYELEMENTS(ElementTag,ElementType,Result, Tag) \ | |
2269 \ | |
2270 JNI_QUICK_ENTRY(ElementType*, \ | |
2271 jni_Get##Result##ArrayElements(JNIEnv *env, ElementType##Array array, jboolean *isCopy)) \ | |
2272 JNIWrapper("Get" XSTR(Result) "ArrayElements"); \ | |
2273 DTRACE_PROBE3(hotspot_jni, Get##Result##ArrayElements__entry, env, array, isCopy);\ | |
2274 /* allocate an chunk of memory in c land */ \ | |
2275 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | |
2276 ElementType* result; \ | |
2277 int len = a->length(); \ | |
2278 if (len == 0) { \ | |
2279 /* Empty array: legal but useless, can't return NULL. \ | |
2280 * Return a pointer to something useless. \ | |
2281 * Avoid asserts in typeArrayOop. */ \ | |
2282 result = (ElementType*)get_bad_address(); \ | |
2283 } else { \ | |
2284 result = NEW_C_HEAP_ARRAY(ElementType, len); \ | |
2285 /* copy the array to the c chunk */ \ | |
2286 memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \ | |
2287 } \ | |
2288 if (isCopy) *isCopy = JNI_TRUE; \ | |
2289 DTRACE_PROBE1(hotspot_jni, Get##Result##ArrayElements__return, result);\ | |
2290 return result; \ | |
2291 JNI_END | |
2292 | |
2293 DEFINE_GETSCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool) | |
2294 DEFINE_GETSCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte) | |
2295 DEFINE_GETSCALARARRAYELEMENTS(T_SHORT, jshort, Short, short) | |
2296 DEFINE_GETSCALARARRAYELEMENTS(T_CHAR, jchar, Char, char) | |
2297 DEFINE_GETSCALARARRAYELEMENTS(T_INT, jint, Int, int) | |
2298 DEFINE_GETSCALARARRAYELEMENTS(T_LONG, jlong, Long, long) | |
2299 DEFINE_GETSCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) | |
2300 DEFINE_GETSCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) | |
2301 | |
2302 | |
2303 #define DEFINE_RELEASESCALARARRAYELEMENTS(ElementTag,ElementType,Result,Tag) \ | |
2304 \ | |
2305 JNI_QUICK_ENTRY(void, \ | |
2306 jni_Release##Result##ArrayElements(JNIEnv *env, ElementType##Array array, \ | |
2307 ElementType *buf, jint mode)) \ | |
2308 JNIWrapper("Release" XSTR(Result) "ArrayElements"); \ | |
2309 DTRACE_PROBE4(hotspot_jni, Release##Result##ArrayElements__entry, env, array, buf, mode);\ | |
2310 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | |
2311 int len = a->length(); \ | |
2312 if (len != 0) { /* Empty array: nothing to free or copy. */ \ | |
2313 if ((mode == 0) || (mode == JNI_COMMIT)) { \ | |
2314 memcpy(a->Tag##_at_addr(0), buf, sizeof(ElementType)*len); \ | |
2315 } \ | |
2316 if ((mode == 0) || (mode == JNI_ABORT)) { \ | |
2317 FreeHeap(buf); \ | |
2318 } \ | |
2319 } \ | |
2320 DTRACE_PROBE(hotspot_jni, Release##Result##ArrayElements__return);\ | |
2321 JNI_END | |
2322 | |
2323 DEFINE_RELEASESCALARARRAYELEMENTS(T_BOOLEAN, jboolean, Boolean, bool) | |
2324 DEFINE_RELEASESCALARARRAYELEMENTS(T_BYTE, jbyte, Byte, byte) | |
2325 DEFINE_RELEASESCALARARRAYELEMENTS(T_SHORT, jshort, Short, short) | |
2326 DEFINE_RELEASESCALARARRAYELEMENTS(T_CHAR, jchar, Char, char) | |
2327 DEFINE_RELEASESCALARARRAYELEMENTS(T_INT, jint, Int, int) | |
2328 DEFINE_RELEASESCALARARRAYELEMENTS(T_LONG, jlong, Long, long) | |
2329 DEFINE_RELEASESCALARARRAYELEMENTS(T_FLOAT, jfloat, Float, float) | |
2330 DEFINE_RELEASESCALARARRAYELEMENTS(T_DOUBLE, jdouble, Double, double) | |
2331 | |
2332 #define DEFINE_GETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ | |
2333 DT_VOID_RETURN_MARK_DECL(Get##Result##ArrayRegion);\ | |
2334 \ | |
2335 JNI_ENTRY(void, \ | |
2336 jni_Get##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ | |
2337 jsize len, ElementType *buf)) \ | |
2338 JNIWrapper("Get" XSTR(Result) "ArrayRegion"); \ | |
2339 DTRACE_PROBE5(hotspot_jni, Get##Result##ArrayRegion__entry, env, array, start, len, buf);\ | |
2340 DT_VOID_RETURN_MARK(Get##Result##ArrayRegion); \ | |
2341 typeArrayOop src = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | |
2342 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)src->length())) { \ | |
2343 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ | |
2344 } else { \ | |
2345 if (len > 0) { \ | |
2346 int sc = typeArrayKlass::cast(src->klass())->log2_element_size(); \ | |
2347 memcpy((u_char*) buf, \ | |
2348 (u_char*) src->Tag##_at_addr(start), \ | |
2349 len << sc); \ | |
2350 } \ | |
2351 } \ | |
2352 JNI_END | |
2353 | |
2354 DEFINE_GETSCALARARRAYREGION(T_BOOLEAN, jboolean,Boolean, bool) | |
2355 DEFINE_GETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte) | |
2356 DEFINE_GETSCALARARRAYREGION(T_SHORT, jshort, Short, short) | |
2357 DEFINE_GETSCALARARRAYREGION(T_CHAR, jchar, Char, char) | |
2358 DEFINE_GETSCALARARRAYREGION(T_INT, jint, Int, int) | |
2359 DEFINE_GETSCALARARRAYREGION(T_LONG, jlong, Long, long) | |
2360 DEFINE_GETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) | |
2361 DEFINE_GETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) | |
2362 | |
2363 #define DEFINE_SETSCALARARRAYREGION(ElementTag,ElementType,Result, Tag) \ | |
2364 DT_VOID_RETURN_MARK_DECL(Set##Result##ArrayRegion);\ | |
2365 \ | |
2366 JNI_ENTRY(void, \ | |
2367 jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \ | |
2368 jsize len, const ElementType *buf)) \ | |
2369 JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \ | |
2370 DTRACE_PROBE5(hotspot_jni, Set##Result##ArrayRegion__entry, env, array, start, len, buf);\ | |
2371 DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \ | |
2372 typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \ | |
2373 if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \ | |
2374 THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \ | |
2375 } else { \ | |
2376 if (len > 0) { \ | |
2377 int sc = typeArrayKlass::cast(dst->klass())->log2_element_size(); \ | |
2378 memcpy((u_char*) dst->Tag##_at_addr(start), \ | |
2379 (u_char*) buf, \ | |
2380 len << sc); \ | |
2381 } \ | |
2382 } \ | |
2383 JNI_END | |
2384 | |
2385 DEFINE_SETSCALARARRAYREGION(T_BOOLEAN, jboolean, Boolean, bool) | |
2386 DEFINE_SETSCALARARRAYREGION(T_BYTE, jbyte, Byte, byte) | |
2387 DEFINE_SETSCALARARRAYREGION(T_SHORT, jshort, Short, short) | |
2388 DEFINE_SETSCALARARRAYREGION(T_CHAR, jchar, Char, char) | |
2389 DEFINE_SETSCALARARRAYREGION(T_INT, jint, Int, int) | |
2390 DEFINE_SETSCALARARRAYREGION(T_LONG, jlong, Long, long) | |
2391 DEFINE_SETSCALARARRAYREGION(T_FLOAT, jfloat, Float, float) | |
2392 DEFINE_SETSCALARARRAYREGION(T_DOUBLE, jdouble, Double, double) | |
2393 | |
2394 | |
2395 // | |
2396 // Interception of natives | |
2397 // | |
2398 | |
2399 // The RegisterNatives call being attempted tried to register with a method that | |
2400 // is not native. Ask JVM TI what prefixes have been specified. Then check | |
2401 // to see if the native method is now wrapped with the prefixes. See the | |
2402 // SetNativeMethodPrefix(es) functions in the JVM TI Spec for details. | |
2403 static methodOop find_prefixed_native(KlassHandle k, | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2404 Symbol* name, Symbol* signature, TRAPS) { |
0 | 2405 ResourceMark rm(THREAD); |
2406 methodOop method; | |
2407 int name_len = name->utf8_length(); | |
2408 char* name_str = name->as_utf8(); | |
2409 int prefix_count; | |
2410 char** prefixes = JvmtiExport::get_all_native_method_prefixes(&prefix_count); | |
2411 for (int i = 0; i < prefix_count; i++) { | |
2412 char* prefix = prefixes[i]; | |
2413 int prefix_len = (int)strlen(prefix); | |
2414 | |
2415 // try adding this prefix to the method name and see if it matches another method name | |
2416 int trial_len = name_len + prefix_len; | |
2417 char* trial_name_str = NEW_RESOURCE_ARRAY(char, trial_len + 1); | |
2418 strcpy(trial_name_str, prefix); | |
2419 strcat(trial_name_str, name_str); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2420 TempNewSymbol trial_name = SymbolTable::probe(trial_name_str, trial_len); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2421 if (trial_name == NULL) { |
0 | 2422 continue; // no such symbol, so this prefix wasn't used, try the next prefix |
2423 } | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2424 method = Klass::cast(k())->lookup_method(trial_name, signature); |
0 | 2425 if (method == NULL) { |
2426 continue; // signature doesn't match, try the next prefix | |
2427 } | |
2428 if (method->is_native()) { | |
2429 method->set_is_prefixed_native(); | |
2430 return method; // wahoo, we found a prefixed version of the method, return it | |
2431 } | |
2432 // found as non-native, so prefix is good, add it, probably just need more prefixes | |
2433 name_len = trial_len; | |
2434 name_str = trial_name_str; | |
2435 } | |
2436 return NULL; // not found | |
2437 } | |
2438 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2439 static bool register_native(KlassHandle k, Symbol* name, Symbol* signature, address entry, TRAPS) { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2440 methodOop method = Klass::cast(k())->lookup_method(name, signature); |
0 | 2441 if (method == NULL) { |
2442 ResourceMark rm; | |
2443 stringStream st; | |
2444 st.print("Method %s name or signature does not match", | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2445 methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name, signature)); |
0 | 2446 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); |
2447 } | |
2448 if (!method->is_native()) { | |
2449 // trying to register to a non-native method, see if a JVM TI agent has added prefix(es) | |
2450 method = find_prefixed_native(k, name, signature, THREAD); | |
2451 if (method == NULL) { | |
2452 ResourceMark rm; | |
2453 stringStream st; | |
2454 st.print("Method %s is not declared as native", | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2455 methodOopDesc::name_and_sig_as_C_string(Klass::cast(k()), name, signature)); |
0 | 2456 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), false); |
2457 } | |
2458 } | |
2459 | |
2460 if (entry != NULL) { | |
2461 method->set_native_function(entry, | |
2462 methodOopDesc::native_bind_event_is_interesting); | |
2463 } else { | |
2464 method->clear_native_function(); | |
2465 } | |
2466 if (PrintJNIResolving) { | |
2467 ResourceMark rm(THREAD); | |
2468 tty->print_cr("[Registering JNI native method %s.%s]", | |
2469 Klass::cast(method->method_holder())->external_name(), | |
2470 method->name()->as_C_string()); | |
2471 } | |
2472 return true; | |
2473 } | |
2474 | |
2475 DT_RETURN_MARK_DECL(RegisterNatives, jint); | |
2476 | |
2477 JNI_ENTRY(jint, jni_RegisterNatives(JNIEnv *env, jclass clazz, | |
2478 const JNINativeMethod *methods, | |
2479 jint nMethods)) | |
2480 JNIWrapper("RegisterNatives"); | |
2481 DTRACE_PROBE4(hotspot_jni, RegisterNatives__entry, env, clazz, methods, nMethods); | |
2482 jint ret = 0; | |
2483 DT_RETURN_MARK(RegisterNatives, jint, (const jint&)ret); | |
2484 | |
2485 KlassHandle h_k(thread, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz))); | |
2486 | |
2487 for (int index = 0; index < nMethods; index++) { | |
2488 const char* meth_name = methods[index].name; | |
2489 const char* meth_sig = methods[index].signature; | |
2490 int meth_name_len = (int)strlen(meth_name); | |
2491 | |
2492 // The class should have been loaded (we have an instance of the class | |
2493 // passed in) so the method and signature should already be in the symbol | |
2494 // table. If they're not there, the method doesn't exist. | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2495 TempNewSymbol name = SymbolTable::probe(meth_name, meth_name_len); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2496 TempNewSymbol signature = SymbolTable::probe(meth_sig, (int)strlen(meth_sig)); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2497 |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2498 if (name == NULL || signature == NULL) { |
0 | 2499 ResourceMark rm; |
2500 stringStream st; | |
2501 st.print("Method %s.%s%s not found", Klass::cast(h_k())->external_name(), meth_name, meth_sig); | |
2502 // Must return negative value on failure | |
2503 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), st.as_string(), -1); | |
2504 } | |
2505 | |
2506 bool res = register_native(h_k, name, signature, | |
2507 (address) methods[index].fnPtr, THREAD); | |
2508 if (!res) { | |
2509 ret = -1; | |
2510 break; | |
2511 } | |
2512 } | |
2513 return ret; | |
2514 JNI_END | |
2515 | |
2516 | |
2517 JNI_ENTRY(jint, jni_UnregisterNatives(JNIEnv *env, jclass clazz)) | |
2518 JNIWrapper("UnregisterNatives"); | |
2519 DTRACE_PROBE2(hotspot_jni, UnregisterNatives__entry, env, clazz); | |
2520 klassOop k = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)); | |
2521 //%note jni_2 | |
2522 if (Klass::cast(k)->oop_is_instance()) { | |
2523 for (int index = 0; index < instanceKlass::cast(k)->methods()->length(); index++) { | |
2524 methodOop m = methodOop(instanceKlass::cast(k)->methods()->obj_at(index)); | |
2525 if (m->is_native()) { | |
2526 m->clear_native_function(); | |
2527 m->set_signature_handler(NULL); | |
2528 } | |
2529 } | |
2530 } | |
2531 DTRACE_PROBE1(hotspot_jni, UnregisterNatives__return, 0); | |
2532 return 0; | |
2533 JNI_END | |
2534 | |
2535 // | |
2536 // Monitor functions | |
2537 // | |
2538 | |
2539 DT_RETURN_MARK_DECL(MonitorEnter, jint); | |
2540 | |
2541 JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj)) | |
2542 DTRACE_PROBE2(hotspot_jni, MonitorEnter__entry, env, jobj); | |
2543 jint ret = JNI_ERR; | |
2544 DT_RETURN_MARK(MonitorEnter, jint, (const jint&)ret); | |
2545 | |
2546 // If the object is null, we can't do anything with it | |
2547 if (jobj == NULL) { | |
2548 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR); | |
2549 } | |
2550 | |
2551 Handle obj(thread, JNIHandles::resolve_non_null(jobj)); | |
2552 ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR)); | |
2553 ret = JNI_OK; | |
2554 return ret; | |
2555 JNI_END | |
2556 | |
2557 DT_RETURN_MARK_DECL(MonitorExit, jint); | |
2558 | |
2559 JNI_ENTRY(jint, jni_MonitorExit(JNIEnv *env, jobject jobj)) | |
2560 DTRACE_PROBE2(hotspot_jni, MonitorExit__entry, env, jobj); | |
2561 jint ret = JNI_ERR; | |
2562 DT_RETURN_MARK(MonitorExit, jint, (const jint&)ret); | |
2563 | |
2564 // Don't do anything with a null object | |
2565 if (jobj == NULL) { | |
2566 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_ERR); | |
2567 } | |
2568 | |
2569 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj)); | |
2570 ObjectSynchronizer::jni_exit(obj(), CHECK_(JNI_ERR)); | |
2571 | |
2572 ret = JNI_OK; | |
2573 return ret; | |
2574 JNI_END | |
2575 | |
2576 // | |
2577 // Extensions | |
2578 // | |
2579 | |
2580 DT_VOID_RETURN_MARK_DECL(GetStringRegion); | |
2581 | |
2582 JNI_ENTRY(void, jni_GetStringRegion(JNIEnv *env, jstring string, jsize start, jsize len, jchar *buf)) | |
2583 JNIWrapper("GetStringRegion"); | |
2584 DTRACE_PROBE5(hotspot_jni, GetStringRegion__entry, env, string, start, len, buf); | |
2585 DT_VOID_RETURN_MARK(GetStringRegion); | |
2586 oop s = JNIHandles::resolve_non_null(string); | |
2587 int s_len = java_lang_String::length(s); | |
2588 if (start < 0 || len < 0 || start + len > s_len) { | |
2589 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); | |
2590 } else { | |
2591 if (len > 0) { | |
2592 int s_offset = java_lang_String::offset(s); | |
2593 typeArrayOop s_value = java_lang_String::value(s); | |
2594 memcpy(buf, s_value->char_at_addr(s_offset+start), sizeof(jchar)*len); | |
2595 } | |
2596 } | |
2597 JNI_END | |
2598 | |
2599 DT_VOID_RETURN_MARK_DECL(GetStringUTFRegion); | |
2600 | |
2601 JNI_ENTRY(void, jni_GetStringUTFRegion(JNIEnv *env, jstring string, jsize start, jsize len, char *buf)) | |
2602 JNIWrapper("GetStringUTFRegion"); | |
2603 DTRACE_PROBE5(hotspot_jni, GetStringUTFRegion__entry, env, string, start, len, buf); | |
2604 DT_VOID_RETURN_MARK(GetStringUTFRegion); | |
2605 oop s = JNIHandles::resolve_non_null(string); | |
2606 int s_len = java_lang_String::length(s); | |
2607 if (start < 0 || len < 0 || start + len > s_len) { | |
2608 THROW(vmSymbols::java_lang_StringIndexOutOfBoundsException()); | |
2609 } else { | |
2610 //%note jni_7 | |
2611 if (len > 0) { | |
2612 ResourceMark rm(THREAD); | |
2613 char *utf_region = java_lang_String::as_utf8_string(s, start, len); | |
2614 int utf_len = (int)strlen(utf_region); | |
2615 memcpy(buf, utf_region, utf_len); | |
2616 buf[utf_len] = 0; | |
2617 } else { | |
2618 // JDK null-terminates the buffer even in len is zero | |
2619 if (buf != NULL) { | |
2620 buf[0] = 0; | |
2621 } | |
2622 } | |
2623 } | |
2624 JNI_END | |
2625 | |
2626 | |
2627 JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)) | |
2628 JNIWrapper("GetPrimitiveArrayCritical"); | |
2629 DTRACE_PROBE3(hotspot_jni, GetPrimitiveArrayCritical__entry, env, array, isCopy); | |
2630 GC_locker::lock_critical(thread); | |
2631 if (isCopy != NULL) { | |
2632 *isCopy = JNI_FALSE; | |
2633 } | |
2634 oop a = JNIHandles::resolve_non_null(array); | |
2635 assert(a->is_array(), "just checking"); | |
2636 BasicType type; | |
2637 if (a->is_objArray()) { | |
2638 type = T_OBJECT; | |
2639 } else { | |
2640 type = typeArrayKlass::cast(a->klass())->element_type(); | |
2641 } | |
2642 void* ret = arrayOop(a)->base(type); | |
2643 DTRACE_PROBE1(hotspot_jni, GetPrimitiveArrayCritical__return, ret); | |
2644 return ret; | |
2645 JNI_END | |
2646 | |
2647 | |
2648 JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)) | |
2649 JNIWrapper("ReleasePrimitiveArrayCritical"); | |
2650 DTRACE_PROBE4(hotspot_jni, ReleasePrimitiveArrayCritical__entry, env, array, carray, mode); | |
2651 // The array, carray and mode arguments are ignored | |
2652 GC_locker::unlock_critical(thread); | |
2653 DTRACE_PROBE(hotspot_jni, ReleasePrimitiveArrayCritical__return); | |
2654 JNI_END | |
2655 | |
2656 | |
2657 JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy)) | |
2658 JNIWrapper("GetStringCritical"); | |
2659 DTRACE_PROBE3(hotspot_jni, GetStringCritical__entry, env, string, isCopy); | |
2660 GC_locker::lock_critical(thread); | |
2661 if (isCopy != NULL) { | |
2662 *isCopy = JNI_FALSE; | |
2663 } | |
2664 oop s = JNIHandles::resolve_non_null(string); | |
2665 int s_len = java_lang_String::length(s); | |
2666 typeArrayOop s_value = java_lang_String::value(s); | |
2667 int s_offset = java_lang_String::offset(s); | |
2668 const jchar* ret; | |
2669 if (s_len > 0) { | |
2670 ret = s_value->char_at_addr(s_offset); | |
2671 } else { | |
2672 ret = (jchar*) s_value->base(T_CHAR); | |
2673 } | |
2674 DTRACE_PROBE1(hotspot_jni, GetStringCritical__return, ret); | |
2675 return ret; | |
2676 JNI_END | |
2677 | |
2678 | |
2679 JNI_ENTRY(void, jni_ReleaseStringCritical(JNIEnv *env, jstring str, const jchar *chars)) | |
2680 JNIWrapper("ReleaseStringCritical"); | |
2681 DTRACE_PROBE3(hotspot_jni, ReleaseStringCritical__entry, env, str, chars); | |
2682 // The str and chars arguments are ignored | |
2683 GC_locker::unlock_critical(thread); | |
2684 DTRACE_PROBE(hotspot_jni, ReleaseStringCritical__return); | |
2685 JNI_END | |
2686 | |
2687 | |
2688 JNI_ENTRY(jweak, jni_NewWeakGlobalRef(JNIEnv *env, jobject ref)) | |
2689 JNIWrapper("jni_NewWeakGlobalRef"); | |
2690 DTRACE_PROBE2(hotspot_jni, NewWeakGlobalRef__entry, env, ref); | |
2691 Handle ref_handle(thread, JNIHandles::resolve(ref)); | |
2692 jweak ret = JNIHandles::make_weak_global(ref_handle); | |
2693 DTRACE_PROBE1(hotspot_jni, NewWeakGlobalRef__return, ret); | |
2694 return ret; | |
2695 JNI_END | |
2696 | |
2697 // Must be JNI_ENTRY (with HandleMark) | |
2698 JNI_ENTRY(void, jni_DeleteWeakGlobalRef(JNIEnv *env, jweak ref)) | |
2699 JNIWrapper("jni_DeleteWeakGlobalRef"); | |
2700 DTRACE_PROBE2(hotspot_jni, DeleteWeakGlobalRef__entry, env, ref); | |
2701 JNIHandles::destroy_weak_global(ref); | |
2702 DTRACE_PROBE(hotspot_jni, DeleteWeakGlobalRef__return); | |
2703 JNI_END | |
2704 | |
2705 | |
2706 JNI_QUICK_ENTRY(jboolean, jni_ExceptionCheck(JNIEnv *env)) | |
2707 JNIWrapper("jni_ExceptionCheck"); | |
2708 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__entry, env); | |
2709 jni_check_async_exceptions(thread); | |
2710 jboolean ret = (thread->has_pending_exception()) ? JNI_TRUE : JNI_FALSE; | |
2711 DTRACE_PROBE1(hotspot_jni, ExceptionCheck__return, ret); | |
2712 return ret; | |
2713 JNI_END | |
2714 | |
2715 | |
2716 // Initialization state for three routines below relating to | |
2717 // java.nio.DirectBuffers | |
2718 static jint directBufferSupportInitializeStarted = 0; | |
2719 static volatile jint directBufferSupportInitializeEnded = 0; | |
2720 static volatile jint directBufferSupportInitializeFailed = 0; | |
2721 static jclass bufferClass = NULL; | |
2722 static jclass directBufferClass = NULL; | |
2723 static jclass directByteBufferClass = NULL; | |
2724 static jmethodID directByteBufferConstructor = NULL; | |
2725 static jfieldID directBufferAddressField = NULL; | |
2726 static jfieldID bufferCapacityField = NULL; | |
2727 | |
2728 static jclass lookupOne(JNIEnv* env, const char* name, TRAPS) { | |
2729 Handle loader; // null (bootstrap) loader | |
2730 Handle protection_domain; // null protection domain | |
2731 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1989
diff
changeset
|
2732 TempNewSymbol sym = SymbolTable::new_symbol(name, CHECK_NULL); |
657
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2733 jclass result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, CHECK_NULL); |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2734 |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2735 if (TraceClassResolution && result != NULL) { |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2736 trace_class_resolution(java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(result))); |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2737 } |
715dceaa89b7
6603316: Improve instrumentation for classes loaded at startup
acorn
parents:
579
diff
changeset
|
2738 return result; |
0 | 2739 } |
2740 | |
2741 // These lookups are done with the NULL (bootstrap) ClassLoader to | |
2742 // circumvent any security checks that would be done by jni_FindClass. | |
2743 JNI_ENTRY(bool, lookupDirectBufferClasses(JNIEnv* env)) | |
2744 { | |
2745 if ((bufferClass = lookupOne(env, "java/nio/Buffer", thread)) == NULL) { return false; } | |
2746 if ((directBufferClass = lookupOne(env, "sun/nio/ch/DirectBuffer", thread)) == NULL) { return false; } | |
2747 if ((directByteBufferClass = lookupOne(env, "java/nio/DirectByteBuffer", thread)) == NULL) { return false; } | |
2748 return true; | |
2749 } | |
2750 JNI_END | |
2751 | |
2752 | |
2753 static bool initializeDirectBufferSupport(JNIEnv* env, JavaThread* thread) { | |
2754 if (directBufferSupportInitializeFailed) { | |
2755 return false; | |
2756 } | |
2757 | |
2758 if (Atomic::cmpxchg(1, &directBufferSupportInitializeStarted, 0) == 0) { | |
2759 if (!lookupDirectBufferClasses(env)) { | |
2760 directBufferSupportInitializeFailed = 1; | |
2761 return false; | |
2762 } | |
2763 | |
2764 // Make global references for these | |
2765 bufferClass = (jclass) env->NewGlobalRef(bufferClass); | |
2766 directBufferClass = (jclass) env->NewGlobalRef(directBufferClass); | |
2767 directByteBufferClass = (jclass) env->NewGlobalRef(directByteBufferClass); | |
2768 | |
2769 // Get needed field and method IDs | |
2770 directByteBufferConstructor = env->GetMethodID(directByteBufferClass, "<init>", "(JI)V"); | |
2771 directBufferAddressField = env->GetFieldID(bufferClass, "address", "J"); | |
2772 bufferCapacityField = env->GetFieldID(bufferClass, "capacity", "I"); | |
2773 | |
2774 if ((directByteBufferConstructor == NULL) || | |
2775 (directBufferAddressField == NULL) || | |
2776 (bufferCapacityField == NULL)) { | |
2777 directBufferSupportInitializeFailed = 1; | |
2778 return false; | |
2779 } | |
2780 | |
2781 directBufferSupportInitializeEnded = 1; | |
2782 } else { | |
2783 while (!directBufferSupportInitializeEnded && !directBufferSupportInitializeFailed) { | |
521
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2784 // Set state as yield_all can call os:sleep. On Solaris, yield_all calls |
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2785 // os::sleep which requires the VM state transition. On other platforms, it |
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2786 // is not necessary. The following call to change the VM state is purposely |
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2787 // put inside the loop to avoid potential deadlock when multiple threads |
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2788 // try to call this method. See 6791815 for more details. |
4db4e58c16bd
6791815: Fix for 6471657 can cause deadlock on non-Solaris platforms when initializing direct buffer support
xlu
parents:
477
diff
changeset
|
2789 ThreadInVMfromNative tivn(thread); |
0 | 2790 os::yield_all(); |
2791 } | |
2792 } | |
2793 | |
2794 return !directBufferSupportInitializeFailed; | |
2795 } | |
2796 | |
2797 extern "C" jobject JNICALL jni_NewDirectByteBuffer(JNIEnv *env, void* address, jlong capacity) | |
2798 { | |
2799 // thread_from_jni_environment() will block if VM is gone. | |
2800 JavaThread* thread = JavaThread::thread_from_jni_environment(env); | |
2801 | |
2802 JNIWrapper("jni_NewDirectByteBuffer"); | |
2803 DTRACE_PROBE3(hotspot_jni, NewDirectByteBuffer__entry, env, address, capacity); | |
2804 | |
2805 if (!directBufferSupportInitializeEnded) { | |
2806 if (!initializeDirectBufferSupport(env, thread)) { | |
2807 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, NULL); | |
2808 return NULL; | |
2809 } | |
2810 } | |
2811 | |
2812 // Being paranoid about accidental sign extension on address | |
2813 jlong addr = (jlong) ((uintptr_t) address); | |
2814 // NOTE that package-private DirectByteBuffer constructor currently | |
2815 // takes int capacity | |
2816 jint cap = (jint) capacity; | |
2817 jobject ret = env->NewObject(directByteBufferClass, directByteBufferConstructor, addr, cap); | |
2818 DTRACE_PROBE1(hotspot_jni, NewDirectByteBuffer__return, ret); | |
2819 return ret; | |
2820 } | |
2821 | |
2822 DT_RETURN_MARK_DECL(GetDirectBufferAddress, void*); | |
2823 | |
2824 extern "C" void* JNICALL jni_GetDirectBufferAddress(JNIEnv *env, jobject buf) | |
2825 { | |
2826 // thread_from_jni_environment() will block if VM is gone. | |
2827 JavaThread* thread = JavaThread::thread_from_jni_environment(env); | |
2828 | |
2829 JNIWrapper("jni_GetDirectBufferAddress"); | |
2830 DTRACE_PROBE2(hotspot_jni, GetDirectBufferAddress__entry, env, buf); | |
2831 void* ret = NULL; | |
2832 DT_RETURN_MARK(GetDirectBufferAddress, void*, (const void*&)ret); | |
2833 | |
2834 if (!directBufferSupportInitializeEnded) { | |
2835 if (!initializeDirectBufferSupport(env, thread)) { | |
2836 return 0; | |
2837 } | |
2838 } | |
2839 | |
2840 if ((buf != NULL) && (!env->IsInstanceOf(buf, directBufferClass))) { | |
2841 return 0; | |
2842 } | |
2843 | |
2844 ret = (void*)(intptr_t)env->GetLongField(buf, directBufferAddressField); | |
2845 return ret; | |
2846 } | |
2847 | |
2848 DT_RETURN_MARK_DECL(GetDirectBufferCapacity, jlong); | |
2849 | |
2850 extern "C" jlong JNICALL jni_GetDirectBufferCapacity(JNIEnv *env, jobject buf) | |
2851 { | |
2852 // thread_from_jni_environment() will block if VM is gone. | |
2853 JavaThread* thread = JavaThread::thread_from_jni_environment(env); | |
2854 | |
2855 JNIWrapper("jni_GetDirectBufferCapacity"); | |
2856 DTRACE_PROBE2(hotspot_jni, GetDirectBufferCapacity__entry, env, buf); | |
2857 jlong ret = -1; | |
2858 DT_RETURN_MARK(GetDirectBufferCapacity, jlong, (const jlong&)ret); | |
2859 | |
2860 if (!directBufferSupportInitializeEnded) { | |
2861 if (!initializeDirectBufferSupport(env, thread)) { | |
2862 ret = 0; | |
2863 return ret; | |
2864 } | |
2865 } | |
2866 | |
2867 if (buf == NULL) { | |
2868 return -1; | |
2869 } | |
2870 | |
2871 if (!env->IsInstanceOf(buf, directBufferClass)) { | |
2872 return -1; | |
2873 } | |
2874 | |
2875 // NOTE that capacity is currently an int in the implementation | |
2876 ret = env->GetIntField(buf, bufferCapacityField); | |
2877 return ret; | |
2878 } | |
2879 | |
2880 | |
2881 JNI_LEAF(jint, jni_GetVersion(JNIEnv *env)) | |
2882 JNIWrapper("GetVersion"); | |
2883 DTRACE_PROBE1(hotspot_jni, GetVersion__entry, env); | |
2884 DTRACE_PROBE1(hotspot_jni, GetVersion__return, CurrentVersion); | |
2885 return CurrentVersion; | |
2886 JNI_END | |
2887 | |
2888 extern struct JavaVM_ main_vm; | |
2889 | |
2890 JNI_LEAF(jint, jni_GetJavaVM(JNIEnv *env, JavaVM **vm)) | |
2891 JNIWrapper("jni_GetJavaVM"); | |
2892 DTRACE_PROBE2(hotspot_jni, GetJavaVM__entry, env, vm); | |
2893 *vm = (JavaVM *)(&main_vm); | |
2894 DTRACE_PROBE1(hotspot_jni, GetJavaVM__return, JNI_OK); | |
2895 return JNI_OK; | |
2896 JNI_END | |
2897 | |
2898 // Structure containing all jni functions | |
2899 struct JNINativeInterface_ jni_NativeInterface = { | |
2900 NULL, | |
2901 NULL, | |
2902 NULL, | |
2903 | |
2904 NULL, | |
2905 | |
2906 jni_GetVersion, | |
2907 | |
2908 jni_DefineClass, | |
2909 jni_FindClass, | |
2910 | |
2911 jni_FromReflectedMethod, | |
2912 jni_FromReflectedField, | |
2913 | |
2914 jni_ToReflectedMethod, | |
2915 | |
2916 jni_GetSuperclass, | |
2917 jni_IsAssignableFrom, | |
2918 | |
2919 jni_ToReflectedField, | |
2920 | |
2921 jni_Throw, | |
2922 jni_ThrowNew, | |
2923 jni_ExceptionOccurred, | |
2924 jni_ExceptionDescribe, | |
2925 jni_ExceptionClear, | |
2926 jni_FatalError, | |
2927 | |
2928 jni_PushLocalFrame, | |
2929 jni_PopLocalFrame, | |
2930 | |
2931 jni_NewGlobalRef, | |
2932 jni_DeleteGlobalRef, | |
2933 jni_DeleteLocalRef, | |
2934 jni_IsSameObject, | |
2935 | |
2936 jni_NewLocalRef, | |
2937 jni_EnsureLocalCapacity, | |
2938 | |
2939 jni_AllocObject, | |
2940 jni_NewObject, | |
2941 jni_NewObjectV, | |
2942 jni_NewObjectA, | |
2943 | |
2944 jni_GetObjectClass, | |
2945 jni_IsInstanceOf, | |
2946 | |
2947 jni_GetMethodID, | |
2948 | |
2949 jni_CallObjectMethod, | |
2950 jni_CallObjectMethodV, | |
2951 jni_CallObjectMethodA, | |
2952 jni_CallBooleanMethod, | |
2953 jni_CallBooleanMethodV, | |
2954 jni_CallBooleanMethodA, | |
2955 jni_CallByteMethod, | |
2956 jni_CallByteMethodV, | |
2957 jni_CallByteMethodA, | |
2958 jni_CallCharMethod, | |
2959 jni_CallCharMethodV, | |
2960 jni_CallCharMethodA, | |
2961 jni_CallShortMethod, | |
2962 jni_CallShortMethodV, | |
2963 jni_CallShortMethodA, | |
2964 jni_CallIntMethod, | |
2965 jni_CallIntMethodV, | |
2966 jni_CallIntMethodA, | |
2967 jni_CallLongMethod, | |
2968 jni_CallLongMethodV, | |
2969 jni_CallLongMethodA, | |
2970 jni_CallFloatMethod, | |
2971 jni_CallFloatMethodV, | |
2972 jni_CallFloatMethodA, | |
2973 jni_CallDoubleMethod, | |
2974 jni_CallDoubleMethodV, | |
2975 jni_CallDoubleMethodA, | |
2976 jni_CallVoidMethod, | |
2977 jni_CallVoidMethodV, | |
2978 jni_CallVoidMethodA, | |
2979 | |
2980 jni_CallNonvirtualObjectMethod, | |
2981 jni_CallNonvirtualObjectMethodV, | |
2982 jni_CallNonvirtualObjectMethodA, | |
2983 jni_CallNonvirtualBooleanMethod, | |
2984 jni_CallNonvirtualBooleanMethodV, | |
2985 jni_CallNonvirtualBooleanMethodA, | |
2986 jni_CallNonvirtualByteMethod, | |
2987 jni_CallNonvirtualByteMethodV, | |
2988 jni_CallNonvirtualByteMethodA, | |
2989 jni_CallNonvirtualCharMethod, | |
2990 jni_CallNonvirtualCharMethodV, | |
2991 jni_CallNonvirtualCharMethodA, | |
2992 jni_CallNonvirtualShortMethod, | |
2993 jni_CallNonvirtualShortMethodV, | |
2994 jni_CallNonvirtualShortMethodA, | |
2995 jni_CallNonvirtualIntMethod, | |
2996 jni_CallNonvirtualIntMethodV, | |
2997 jni_CallNonvirtualIntMethodA, | |
2998 jni_CallNonvirtualLongMethod, | |
2999 jni_CallNonvirtualLongMethodV, | |
3000 jni_CallNonvirtualLongMethodA, | |
3001 jni_CallNonvirtualFloatMethod, | |
3002 jni_CallNonvirtualFloatMethodV, | |
3003 jni_CallNonvirtualFloatMethodA, | |
3004 jni_CallNonvirtualDoubleMethod, | |
3005 jni_CallNonvirtualDoubleMethodV, | |
3006 jni_CallNonvirtualDoubleMethodA, | |
3007 jni_CallNonvirtualVoidMethod, | |
3008 jni_CallNonvirtualVoidMethodV, | |
3009 jni_CallNonvirtualVoidMethodA, | |
3010 | |
3011 jni_GetFieldID, | |
3012 | |
3013 jni_GetObjectField, | |
3014 jni_GetBooleanField, | |
3015 jni_GetByteField, | |
3016 jni_GetCharField, | |
3017 jni_GetShortField, | |
3018 jni_GetIntField, | |
3019 jni_GetLongField, | |
3020 jni_GetFloatField, | |
3021 jni_GetDoubleField, | |
3022 | |
3023 jni_SetObjectField, | |
3024 jni_SetBooleanField, | |
3025 jni_SetByteField, | |
3026 jni_SetCharField, | |
3027 jni_SetShortField, | |
3028 jni_SetIntField, | |
3029 jni_SetLongField, | |
3030 jni_SetFloatField, | |
3031 jni_SetDoubleField, | |
3032 | |
3033 jni_GetStaticMethodID, | |
3034 | |
3035 jni_CallStaticObjectMethod, | |
3036 jni_CallStaticObjectMethodV, | |
3037 jni_CallStaticObjectMethodA, | |
3038 jni_CallStaticBooleanMethod, | |
3039 jni_CallStaticBooleanMethodV, | |
3040 jni_CallStaticBooleanMethodA, | |
3041 jni_CallStaticByteMethod, | |
3042 jni_CallStaticByteMethodV, | |
3043 jni_CallStaticByteMethodA, | |
3044 jni_CallStaticCharMethod, | |
3045 jni_CallStaticCharMethodV, | |
3046 jni_CallStaticCharMethodA, | |
3047 jni_CallStaticShortMethod, | |
3048 jni_CallStaticShortMethodV, | |
3049 jni_CallStaticShortMethodA, | |
3050 jni_CallStaticIntMethod, | |
3051 jni_CallStaticIntMethodV, | |
3052 jni_CallStaticIntMethodA, | |
3053 jni_CallStaticLongMethod, | |
3054 jni_CallStaticLongMethodV, | |
3055 jni_CallStaticLongMethodA, | |
3056 jni_CallStaticFloatMethod, | |
3057 jni_CallStaticFloatMethodV, | |
3058 jni_CallStaticFloatMethodA, | |
3059 jni_CallStaticDoubleMethod, | |
3060 jni_CallStaticDoubleMethodV, | |
3061 jni_CallStaticDoubleMethodA, | |
3062 jni_CallStaticVoidMethod, | |
3063 jni_CallStaticVoidMethodV, | |
3064 jni_CallStaticVoidMethodA, | |
3065 | |
3066 jni_GetStaticFieldID, | |
3067 | |
3068 jni_GetStaticObjectField, | |
3069 jni_GetStaticBooleanField, | |
3070 jni_GetStaticByteField, | |
3071 jni_GetStaticCharField, | |
3072 jni_GetStaticShortField, | |
3073 jni_GetStaticIntField, | |
3074 jni_GetStaticLongField, | |
3075 jni_GetStaticFloatField, | |
3076 jni_GetStaticDoubleField, | |
3077 | |
3078 jni_SetStaticObjectField, | |
3079 jni_SetStaticBooleanField, | |
3080 jni_SetStaticByteField, | |
3081 jni_SetStaticCharField, | |
3082 jni_SetStaticShortField, | |
3083 jni_SetStaticIntField, | |
3084 jni_SetStaticLongField, | |
3085 jni_SetStaticFloatField, | |
3086 jni_SetStaticDoubleField, | |
3087 | |
3088 jni_NewString, | |
3089 jni_GetStringLength, | |
3090 jni_GetStringChars, | |
3091 jni_ReleaseStringChars, | |
3092 | |
3093 jni_NewStringUTF, | |
3094 jni_GetStringUTFLength, | |
3095 jni_GetStringUTFChars, | |
3096 jni_ReleaseStringUTFChars, | |
3097 | |
3098 jni_GetArrayLength, | |
3099 | |
3100 jni_NewObjectArray, | |
3101 jni_GetObjectArrayElement, | |
3102 jni_SetObjectArrayElement, | |
3103 | |
3104 jni_NewBooleanArray, | |
3105 jni_NewByteArray, | |
3106 jni_NewCharArray, | |
3107 jni_NewShortArray, | |
3108 jni_NewIntArray, | |
3109 jni_NewLongArray, | |
3110 jni_NewFloatArray, | |
3111 jni_NewDoubleArray, | |
3112 | |
3113 jni_GetBooleanArrayElements, | |
3114 jni_GetByteArrayElements, | |
3115 jni_GetCharArrayElements, | |
3116 jni_GetShortArrayElements, | |
3117 jni_GetIntArrayElements, | |
3118 jni_GetLongArrayElements, | |
3119 jni_GetFloatArrayElements, | |
3120 jni_GetDoubleArrayElements, | |
3121 | |
3122 jni_ReleaseBooleanArrayElements, | |
3123 jni_ReleaseByteArrayElements, | |
3124 jni_ReleaseCharArrayElements, | |
3125 jni_ReleaseShortArrayElements, | |
3126 jni_ReleaseIntArrayElements, | |
3127 jni_ReleaseLongArrayElements, | |
3128 jni_ReleaseFloatArrayElements, | |
3129 jni_ReleaseDoubleArrayElements, | |
3130 | |
3131 jni_GetBooleanArrayRegion, | |
3132 jni_GetByteArrayRegion, | |
3133 jni_GetCharArrayRegion, | |
3134 jni_GetShortArrayRegion, | |
3135 jni_GetIntArrayRegion, | |
3136 jni_GetLongArrayRegion, | |
3137 jni_GetFloatArrayRegion, | |
3138 jni_GetDoubleArrayRegion, | |
3139 | |
3140 jni_SetBooleanArrayRegion, | |
3141 jni_SetByteArrayRegion, | |
3142 jni_SetCharArrayRegion, | |
3143 jni_SetShortArrayRegion, | |
3144 jni_SetIntArrayRegion, | |
3145 jni_SetLongArrayRegion, | |
3146 jni_SetFloatArrayRegion, | |
3147 jni_SetDoubleArrayRegion, | |
3148 | |
3149 jni_RegisterNatives, | |
3150 jni_UnregisterNatives, | |
3151 | |
3152 jni_MonitorEnter, | |
3153 jni_MonitorExit, | |
3154 | |
3155 jni_GetJavaVM, | |
3156 | |
3157 jni_GetStringRegion, | |
3158 jni_GetStringUTFRegion, | |
3159 | |
3160 jni_GetPrimitiveArrayCritical, | |
3161 jni_ReleasePrimitiveArrayCritical, | |
3162 | |
3163 jni_GetStringCritical, | |
3164 jni_ReleaseStringCritical, | |
3165 | |
3166 jni_NewWeakGlobalRef, | |
3167 jni_DeleteWeakGlobalRef, | |
3168 | |
3169 jni_ExceptionCheck, | |
3170 | |
3171 jni_NewDirectByteBuffer, | |
3172 jni_GetDirectBufferAddress, | |
3173 jni_GetDirectBufferCapacity, | |
3174 | |
3175 // New 1_6 features | |
3176 | |
3177 jni_GetObjectRefType | |
3178 }; | |
3179 | |
3180 | |
3181 // For jvmti use to modify jni function table. | |
3182 // Java threads in native contiues to run until it is transitioned | |
3183 // to VM at safepoint. Before the transition or before it is blocked | |
3184 // for safepoint it may access jni function table. VM could crash if | |
3185 // any java thread access the jni function table in the middle of memcpy. | |
3186 // To avoid this each function pointers are copied automically. | |
3187 void copy_jni_function_table(const struct JNINativeInterface_ *new_jni_NativeInterface) { | |
3188 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); | |
3189 intptr_t *a = (intptr_t *) jni_functions(); | |
3190 intptr_t *b = (intptr_t *) new_jni_NativeInterface; | |
3191 for (uint i=0; i < sizeof(struct JNINativeInterface_)/sizeof(void *); i++) { | |
3192 Atomic::store_ptr(*b++, a++); | |
3193 } | |
3194 } | |
3195 | |
3196 void quicken_jni_functions() { | |
3197 // Replace Get<Primitive>Field with fast versions | |
3198 if (UseFastJNIAccessors && !JvmtiExport::can_post_field_access() | |
3199 && !VerifyJNIFields && !TraceJNICalls && !CountJNICalls && !CheckJNICalls | |
3200 #if defined(_WINDOWS) && defined(IA32) && defined(COMPILER2) | |
3201 // windows x86 currently needs SEH wrapper and the gain of the fast | |
3202 // versions currently isn't certain for server vm on uniprocessor. | |
3203 && os::is_MP() | |
3204 #endif | |
3205 ) { | |
3206 address func; | |
3207 func = JNI_FastGetField::generate_fast_get_boolean_field(); | |
3208 if (func != (address)-1) { | |
3209 jni_NativeInterface.GetBooleanField = (GetBooleanField_t)func; | |
3210 } | |
3211 func = JNI_FastGetField::generate_fast_get_byte_field(); | |
3212 if (func != (address)-1) { | |
3213 jni_NativeInterface.GetByteField = (GetByteField_t)func; | |
3214 } | |
3215 func = JNI_FastGetField::generate_fast_get_char_field(); | |
3216 if (func != (address)-1) { | |
3217 jni_NativeInterface.GetCharField = (GetCharField_t)func; | |
3218 } | |
3219 func = JNI_FastGetField::generate_fast_get_short_field(); | |
3220 if (func != (address)-1) { | |
3221 jni_NativeInterface.GetShortField = (GetShortField_t)func; | |
3222 } | |
3223 func = JNI_FastGetField::generate_fast_get_int_field(); | |
3224 if (func != (address)-1) { | |
3225 jni_NativeInterface.GetIntField = (GetIntField_t)func; | |
3226 } | |
3227 func = JNI_FastGetField::generate_fast_get_long_field(); | |
3228 if (func != (address)-1) { | |
3229 jni_NativeInterface.GetLongField = (GetLongField_t)func; | |
3230 } | |
3231 func = JNI_FastGetField::generate_fast_get_float_field(); | |
3232 if (func != (address)-1) { | |
3233 jni_NativeInterface.GetFloatField = (GetFloatField_t)func; | |
3234 } | |
3235 func = JNI_FastGetField::generate_fast_get_double_field(); | |
3236 if (func != (address)-1) { | |
3237 jni_NativeInterface.GetDoubleField = (GetDoubleField_t)func; | |
3238 } | |
3239 } | |
3240 } | |
3241 | |
3242 // Returns the function structure | |
3243 struct JNINativeInterface_* jni_functions() { | |
3244 #ifndef JNICHECK_KERNEL | |
3245 if (CheckJNICalls) return jni_functions_check(); | |
3246 #else // JNICHECK_KERNEL | |
3247 if (CheckJNICalls) warning("-Xcheck:jni is not supported in kernel vm."); | |
3248 #endif // JNICHECK_KERNEL | |
3249 return &jni_NativeInterface; | |
3250 } | |
3251 | |
3252 // Returns the function structure | |
3253 struct JNINativeInterface_* jni_functions_nocheck() { | |
3254 return &jni_NativeInterface; | |
3255 } | |
3256 | |
3257 | |
3258 // Invocation API | |
3259 | |
3260 | |
3261 // Forward declaration | |
3262 extern const struct JNIInvokeInterface_ jni_InvokeInterface; | |
3263 | |
3264 // Global invocation API vars | |
3265 volatile jint vm_created = 0; | |
3266 // Indicate whether it is safe to recreate VM | |
3267 volatile jint safe_to_recreate_vm = 1; | |
3268 struct JavaVM_ main_vm = {&jni_InvokeInterface}; | |
3269 | |
3270 | |
3271 #define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */ | |
3272 enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL }; | |
3273 | |
3274 HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*); | |
3275 DT_RETURN_MARK_DECL(GetDefaultJavaVMInitArgs, jint); | |
3276 | |
3277 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { | |
3278 HS_DTRACE_PROBE1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, args_); | |
3279 JDK1_1InitArgs *args = (JDK1_1InitArgs *)args_; | |
3280 jint ret = JNI_ERR; | |
3281 DT_RETURN_MARK(GetDefaultJavaVMInitArgs, jint, (const jint&)ret); | |
3282 | |
3283 if (Threads::is_supported_jni_version(args->version)) { | |
3284 ret = JNI_OK; | |
3285 } | |
3286 // 1.1 style no longer supported in hotspot. | |
3287 // According the JNI spec, we should update args->version on return. | |
3288 // We also use the structure to communicate with launcher about default | |
3289 // stack size. | |
3290 if (args->version == JNI_VERSION_1_1) { | |
3291 args->version = JNI_VERSION_1_2; | |
3292 // javaStackSize is int in arguments structure | |
3293 assert(jlong(ThreadStackSize) * K < INT_MAX, "integer overflow"); | |
3294 args->javaStackSize = (jint)(ThreadStackSize * K); | |
3295 } | |
3296 return ret; | |
3297 } | |
3298 | |
3299 HS_DTRACE_PROBE_DECL3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); | |
3300 DT_RETURN_MARK_DECL(CreateJavaVM, jint); | |
3301 | |
3302 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM **vm, void **penv, void *args) { | |
3303 HS_DTRACE_PROBE3(hotspot_jni, CreateJavaVM__entry, vm, penv, args); | |
3304 | |
3305 jint result = JNI_ERR; | |
3306 DT_RETURN_MARK(CreateJavaVM, jint, (const jint&)result); | |
3307 | |
1078 | 3308 // We're about to use Atomic::xchg for synchronization. Some Zero |
3309 // platforms use the GCC builtin __sync_lock_test_and_set for this, | |
3310 // but __sync_lock_test_and_set is not guaranteed to do what we want | |
3311 // on all architectures. So we check it works before relying on it. | |
3312 #if defined(ZERO) && defined(ASSERT) | |
3313 { | |
3314 jint a = 0xcafebabe; | |
3315 jint b = Atomic::xchg(0xdeadbeef, &a); | |
3316 void *c = &a; | |
3317 void *d = Atomic::xchg_ptr(&b, &c); | |
1132 | 3318 assert(a == (jint) 0xdeadbeef && b == (jint) 0xcafebabe, "Atomic::xchg() works"); |
1078 | 3319 assert(c == &b && d == &a, "Atomic::xchg_ptr() works"); |
3320 } | |
3321 #endif // ZERO && ASSERT | |
3322 | |
0 | 3323 // At the moment it's only possible to have one Java VM, |
3324 // since some of the runtime state is in global variables. | |
3325 | |
3326 // We cannot use our mutex locks here, since they only work on | |
3327 // Threads. We do an atomic compare and exchange to ensure only | |
3328 // one thread can call this method at a time | |
3329 | |
3330 // We use Atomic::xchg rather than Atomic::add/dec since on some platforms | |
3331 // the add/dec implementations are dependent on whether we are running | |
3332 // on a multiprocessor, and at this stage of initialization the os::is_MP | |
3333 // function used to determine this will always return false. Atomic::xchg | |
3334 // does not have this problem. | |
3335 if (Atomic::xchg(1, &vm_created) == 1) { | |
3336 return JNI_ERR; // already created, or create attempt in progress | |
3337 } | |
3338 if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) { | |
3339 return JNI_ERR; // someone tried and failed and retry not allowed. | |
3340 } | |
3341 | |
3342 assert(vm_created == 1, "vm_created is true during the creation"); | |
3343 | |
3344 /** | |
3345 * Certain errors during initialization are recoverable and do not | |
3346 * prevent this method from being called again at a later time | |
3347 * (perhaps with different arguments). However, at a certain | |
3348 * point during initialization if an error occurs we cannot allow | |
3349 * this function to be called again (or it will crash). In those | |
3350 * situations, the 'canTryAgain' flag is set to false, which atomically | |
3351 * sets safe_to_recreate_vm to 1, such that any new call to | |
3352 * JNI_CreateJavaVM will immediately fail using the above logic. | |
3353 */ | |
3354 bool can_try_again = true; | |
3355 | |
3356 result = Threads::create_vm((JavaVMInitArgs*) args, &can_try_again); | |
3357 if (result == JNI_OK) { | |
3358 JavaThread *thread = JavaThread::current(); | |
3359 /* thread is thread_in_vm here */ | |
3360 *vm = (JavaVM *)(&main_vm); | |
3361 *(JNIEnv**)penv = thread->jni_environment(); | |
3362 | |
3363 // Tracks the time application was running before GC | |
3364 RuntimeService::record_application_start(); | |
3365 | |
3366 // Notify JVMTI | |
3367 if (JvmtiExport::should_post_thread_life()) { | |
3368 JvmtiExport::post_thread_start(thread); | |
3369 } | |
3370 // Check if we should compile all classes on bootclasspath | |
3371 NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) | |
3372 // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. | |
3373 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); | |
3374 } else { | |
3375 if (can_try_again) { | |
3376 // reset safe_to_recreate_vm to 1 so that retrial would be possible | |
3377 safe_to_recreate_vm = 1; | |
3378 } | |
3379 | |
3380 // Creation failed. We must reset vm_created | |
3381 *vm = 0; | |
3382 *(JNIEnv**)penv = 0; | |
3383 // reset vm_created last to avoid race condition. Use OrderAccess to | |
3384 // control both compiler and architectural-based reordering. | |
3385 OrderAccess::release_store(&vm_created, 0); | |
3386 } | |
3387 | |
1490
f03d0a26bf83
6888954: argument formatting for assert() and friends
jcoomes
parents:
1290
diff
changeset
|
3388 NOT_PRODUCT(test_error_handler(ErrorHandlerTest)); |
0 | 3389 return result; |
3390 } | |
3391 | |
3392 HS_DTRACE_PROBE_DECL3(hotspot_jni, GetCreatedJavaVMs__entry, \ | |
3393 JavaVM**, jsize, jsize*); | |
3394 HS_DTRACE_PROBE_DECL1(hotspot_jni, GetCreatedJavaVMs__return, jint); | |
3395 | |
3396 _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vm_buf, jsize bufLen, jsize *numVMs) { | |
3397 // See bug 4367188, the wrapper can sometimes cause VM crashes | |
3398 // JNIWrapper("GetCreatedJavaVMs"); | |
3399 HS_DTRACE_PROBE3(hotspot_jni, GetCreatedJavaVMs__entry, \ | |
3400 vm_buf, bufLen, numVMs); | |
3401 if (vm_created) { | |
3402 if (numVMs != NULL) *numVMs = 1; | |
3403 if (bufLen > 0) *vm_buf = (JavaVM *)(&main_vm); | |
3404 } else { | |
3405 if (numVMs != NULL) *numVMs = 0; | |
3406 } | |
3407 HS_DTRACE_PROBE1(hotspot_jni, GetCreatedJavaVMs__return, JNI_OK); | |
3408 return JNI_OK; | |
3409 } | |
3410 | |
3411 extern "C" { | |
3412 | |
3413 DT_RETURN_MARK_DECL(DestroyJavaVM, jint); | |
3414 | |
3415 jint JNICALL jni_DestroyJavaVM(JavaVM *vm) { | |
3416 DTRACE_PROBE1(hotspot_jni, DestroyJavaVM__entry, vm); | |
3417 jint res = JNI_ERR; | |
3418 DT_RETURN_MARK(DestroyJavaVM, jint, (const jint&)res); | |
3419 | |
3420 if (!vm_created) { | |
3421 res = JNI_ERR; | |
3422 return res; | |
3423 } | |
3424 | |
3425 JNIWrapper("DestroyJavaVM"); | |
3426 JNIEnv *env; | |
3427 JavaVMAttachArgs destroyargs; | |
3428 destroyargs.version = CurrentVersion; | |
3429 destroyargs.name = (char *)"DestroyJavaVM"; | |
3430 destroyargs.group = NULL; | |
3431 res = vm->AttachCurrentThread((void **)&env, (void *)&destroyargs); | |
3432 if (res != JNI_OK) { | |
3433 return res; | |
3434 } | |
3435 | |
3436 // Since this is not a JVM_ENTRY we have to set the thread state manually before entering. | |
3437 JavaThread* thread = JavaThread::current(); | |
3438 ThreadStateTransition::transition_from_native(thread, _thread_in_vm); | |
3439 if (Threads::destroy_vm()) { | |
3440 // Should not change thread state, VM is gone | |
3441 vm_created = false; | |
3442 res = JNI_OK; | |
3443 return res; | |
3444 } else { | |
3445 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); | |
3446 res = JNI_ERR; | |
3447 return res; | |
3448 } | |
3449 } | |
3450 | |
3451 | |
3452 static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool daemon) { | |
3453 JavaVMAttachArgs *args = (JavaVMAttachArgs *) _args; | |
3454 | |
3455 // Check below commented out from JDK1.2fcs as well | |
3456 /* | |
3457 if (args && (args->version != JNI_VERSION_1_1 || args->version != JNI_VERSION_1_2)) { | |
3458 return JNI_EVERSION; | |
3459 } | |
3460 */ | |
3461 | |
3462 Thread* t = ThreadLocalStorage::get_thread_slow(); | |
3463 if (t != NULL) { | |
3464 // If the thread has been attached this operation is a no-op | |
3465 *(JNIEnv**)penv = ((JavaThread*) t)->jni_environment(); | |
3466 return JNI_OK; | |
3467 } | |
3468 | |
3469 // Create a thread and mark it as attaching so it will be skipped by the | |
3470 // ThreadsListEnumerator - see CR 6404306 | |
3471 JavaThread* thread = new JavaThread(true); | |
3472 | |
3473 // Set correct safepoint info. The thread is going to call into Java when | |
3474 // initializing the Java level thread object. Hence, the correct state must | |
3475 // be set in order for the Safepoint code to deal with it correctly. | |
3476 thread->set_thread_state(_thread_in_vm); | |
3477 // Must do this before initialize_thread_local_storage | |
3478 thread->record_stack_base_and_size(); | |
1290
c8a467bf56ad
6914050: jvm assertion "guard pages must be in use" in -Xcomp mode
coleenp
parents:
1142
diff
changeset
|
3479 |
0 | 3480 thread->initialize_thread_local_storage(); |
3481 | |
3482 if (!os::create_attached_thread(thread)) { | |
3483 delete thread; | |
3484 return JNI_ERR; | |
3485 } | |
1290
c8a467bf56ad
6914050: jvm assertion "guard pages must be in use" in -Xcomp mode
coleenp
parents:
1142
diff
changeset
|
3486 // Enable stack overflow checks |
c8a467bf56ad
6914050: jvm assertion "guard pages must be in use" in -Xcomp mode
coleenp
parents:
1142
diff
changeset
|
3487 thread->create_stack_guard_pages(); |
c8a467bf56ad
6914050: jvm assertion "guard pages must be in use" in -Xcomp mode
coleenp
parents:
1142
diff
changeset
|
3488 |
0 | 3489 thread->initialize_tlab(); |
3490 | |
1681
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
3491 thread->cache_global_variables(); |
126ea7725993
6953477: Increase portability and flexibility of building Hotspot
bobv
parents:
1552
diff
changeset
|
3492 |
0 | 3493 // Crucial that we do not have a safepoint check for this thread, since it has |
3494 // not been added to the Thread list yet. | |
3495 { Threads_lock->lock_without_safepoint_check(); | |
3496 // This must be inside this lock in order to get FullGCALot to work properly, i.e., to | |
3497 // avoid this thread trying to do a GC before it is added to the thread-list | |
3498 thread->set_active_handles(JNIHandleBlock::allocate_block()); | |
3499 Threads::add(thread, daemon); | |
3500 Threads_lock->unlock(); | |
3501 } | |
3502 // Create thread group and name info from attach arguments | |
3503 oop group = NULL; | |
3504 char* thread_name = NULL; | |
3505 if (args != NULL && Threads::is_supported_jni_version(args->version)) { | |
3506 group = JNIHandles::resolve(args->group); | |
3507 thread_name = args->name; // may be NULL | |
3508 } | |
3509 if (group == NULL) group = Universe::main_thread_group(); | |
3510 | |
3511 // Create Java level thread object and attach it to this thread | |
3512 bool attach_failed = false; | |
3513 { | |
3514 EXCEPTION_MARK; | |
3515 HandleMark hm(THREAD); | |
3516 Handle thread_group(THREAD, group); | |
3517 thread->allocate_threadObj(thread_group, thread_name, daemon, THREAD); | |
3518 if (HAS_PENDING_EXCEPTION) { | |
3519 CLEAR_PENDING_EXCEPTION; | |
3520 // cleanup outside the handle mark. | |
3521 attach_failed = true; | |
3522 } | |
3523 } | |
3524 | |
3525 if (attach_failed) { | |
3526 // Added missing cleanup | |
3527 thread->cleanup_failed_attach_current_thread(); | |
3528 return JNI_ERR; | |
3529 } | |
3530 | |
3531 // mark the thread as no longer attaching | |
3532 // this uses a fence to push the change through so we don't have | |
3533 // to regrab the threads_lock | |
3534 thread->set_attached(); | |
3535 | |
3536 // Set java thread status. | |
3537 java_lang_Thread::set_thread_status(thread->threadObj(), | |
3538 java_lang_Thread::RUNNABLE); | |
3539 | |
3540 // Notify the debugger | |
3541 if (JvmtiExport::should_post_thread_life()) { | |
3542 JvmtiExport::post_thread_start(thread); | |
3543 } | |
3544 | |
3545 *(JNIEnv**)penv = thread->jni_environment(); | |
3546 | |
3547 // Now leaving the VM, so change thread_state. This is normally automatically taken care | |
3548 // of in the JVM_ENTRY. But in this situation we have to do it manually. Notice, that by | |
3549 // using ThreadStateTransition::transition, we do a callback to the safepoint code if | |
3550 // needed. | |
3551 | |
3552 ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); | |
3553 | |
3554 // Perform any platform dependent FPU setup | |
3555 os::setup_fpu(); | |
3556 | |
3557 return JNI_OK; | |
3558 } | |
3559 | |
3560 | |
3561 jint JNICALL jni_AttachCurrentThread(JavaVM *vm, void **penv, void *_args) { | |
3562 DTRACE_PROBE3(hotspot_jni, AttachCurrentThread__entry, vm, penv, _args); | |
3563 if (!vm_created) { | |
3564 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, JNI_ERR); | |
3565 return JNI_ERR; | |
3566 } | |
3567 | |
3568 JNIWrapper("AttachCurrentThread"); | |
3569 jint ret = attach_current_thread(vm, penv, _args, false); | |
3570 DTRACE_PROBE1(hotspot_jni, AttachCurrentThread__return, ret); | |
3571 return ret; | |
3572 } | |
3573 | |
3574 | |
3575 jint JNICALL jni_DetachCurrentThread(JavaVM *vm) { | |
3576 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__entry, vm); | |
3577 VM_Exit::block_if_vm_exited(); | |
3578 | |
3579 JNIWrapper("DetachCurrentThread"); | |
3580 | |
3581 // If the thread has been deattacted the operations is a no-op | |
3582 if (ThreadLocalStorage::thread() == NULL) { | |
3583 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); | |
3584 return JNI_OK; | |
3585 } | |
3586 | |
3587 JavaThread* thread = JavaThread::current(); | |
3588 if (thread->has_last_Java_frame()) { | |
3589 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_ERR); | |
3590 // Can't detach a thread that's running java, that can't work. | |
3591 return JNI_ERR; | |
3592 } | |
3593 | |
3594 // Safepoint support. Have to do call-back to safepoint code, if in the | |
3595 // middel of a safepoint operation | |
3596 ThreadStateTransition::transition_from_native(thread, _thread_in_vm); | |
3597 | |
3598 // XXX: Note that JavaThread::exit() call below removes the guards on the | |
3599 // stack pages set up via enable_stack_{red,yellow}_zone() calls | |
3600 // above in jni_AttachCurrentThread. Unfortunately, while the setting | |
3601 // of the guards is visible in jni_AttachCurrentThread above, | |
3602 // the removal of the guards is buried below in JavaThread::exit() | |
3603 // here. The abstraction should be more symmetrically either exposed | |
3604 // or hidden (e.g. it could probably be hidden in the same | |
3605 // (platform-dependent) methods where we do alternate stack | |
3606 // maintenance work?) | |
3607 thread->exit(false, JavaThread::jni_detach); | |
3608 delete thread; | |
3609 | |
3610 DTRACE_PROBE1(hotspot_jni, DetachCurrentThread__return, JNI_OK); | |
3611 return JNI_OK; | |
3612 } | |
3613 | |
3614 DT_RETURN_MARK_DECL(GetEnv, jint); | |
3615 | |
3616 jint JNICALL jni_GetEnv(JavaVM *vm, void **penv, jint version) { | |
3617 DTRACE_PROBE3(hotspot_jni, GetEnv__entry, vm, penv, version); | |
3618 jint ret = JNI_ERR; | |
3619 DT_RETURN_MARK(GetEnv, jint, (const jint&)ret); | |
3620 | |
3621 if (!vm_created) { | |
3622 *penv = NULL; | |
3623 ret = JNI_EDETACHED; | |
3624 return ret; | |
3625 } | |
3626 | |
3627 if (JvmtiExport::is_jvmti_version(version)) { | |
3628 ret = JvmtiExport::get_jvmti_interface(vm, penv, version); | |
3629 return ret; | |
3630 } | |
3631 | |
3632 #ifndef JVMPI_VERSION_1 | |
3633 // need these in order to be polite about older agents | |
3634 #define JVMPI_VERSION_1 ((jint)0x10000001) | |
3635 #define JVMPI_VERSION_1_1 ((jint)0x10000002) | |
3636 #define JVMPI_VERSION_1_2 ((jint)0x10000003) | |
3637 #endif // !JVMPI_VERSION_1 | |
3638 | |
3639 Thread* thread = ThreadLocalStorage::thread(); | |
3640 if (thread != NULL && thread->is_Java_thread()) { | |
3641 if (Threads::is_supported_jni_version_including_1_1(version)) { | |
3642 *(JNIEnv**)penv = ((JavaThread*) thread)->jni_environment(); | |
3643 ret = JNI_OK; | |
3644 return ret; | |
3645 | |
3646 } else if (version == JVMPI_VERSION_1 || | |
3647 version == JVMPI_VERSION_1_1 || | |
3648 version == JVMPI_VERSION_1_2) { | |
3649 tty->print_cr("ERROR: JVMPI, an experimental interface, is no longer supported."); | |
3650 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI)."); | |
3651 ret = JNI_EVERSION; | |
3652 return ret; | |
3653 } else if (JvmtiExport::is_jvmdi_version(version)) { | |
3654 tty->print_cr("FATAL ERROR: JVMDI is no longer supported."); | |
3655 tty->print_cr("Please use the supported interface: the JVM Tool Interface (JVM TI)."); | |
3656 ret = JNI_EVERSION; | |
3657 return ret; | |
3658 } else { | |
3659 *penv = NULL; | |
3660 ret = JNI_EVERSION; | |
3661 return ret; | |
3662 } | |
3663 } else { | |
3664 *penv = NULL; | |
3665 ret = JNI_EDETACHED; | |
3666 return ret; | |
3667 } | |
3668 } | |
3669 | |
3670 | |
3671 jint JNICALL jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *_args) { | |
3672 DTRACE_PROBE3(hotspot_jni, AttachCurrentThreadAsDaemon__entry, vm, penv, _args); | |
3673 if (!vm_created) { | |
3674 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, JNI_ERR); | |
3675 return JNI_ERR; | |
3676 } | |
3677 | |
3678 JNIWrapper("AttachCurrentThreadAsDaemon"); | |
3679 jint ret = attach_current_thread(vm, penv, _args, true); | |
3680 DTRACE_PROBE1(hotspot_jni, AttachCurrentThreadAsDaemon__return, ret); | |
3681 return ret; | |
3682 } | |
3683 | |
3684 | |
3685 } // End extern "C" | |
3686 | |
3687 const struct JNIInvokeInterface_ jni_InvokeInterface = { | |
3688 NULL, | |
3689 NULL, | |
3690 NULL, | |
3691 | |
3692 jni_DestroyJavaVM, | |
3693 jni_AttachCurrentThread, | |
3694 jni_DetachCurrentThread, | |
3695 jni_GetEnv, | |
3696 jni_AttachCurrentThreadAsDaemon | |
3697 }; |