Thu, 05 Sep 2019 18:52:27 +0800
Merge
1 /*
2 * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
25 #include "precompiled.hpp"
27 #include "memory/metadataFactory.hpp"
28 #include "memory/metaspaceShared.hpp"
29 #include "memory/iterator.hpp"
30 #include "memory/universe.hpp"
31 #include "oops/oop.inline.hpp"
33 #include "classfile/symbolTable.hpp"
34 #include "classfile/classLoaderData.hpp"
36 #include "prims/whitebox.hpp"
37 #include "prims/wbtestmethods/parserTests.hpp"
39 #include "runtime/arguments.hpp"
40 #include "runtime/interfaceSupport.hpp"
41 #include "runtime/os.hpp"
42 #include "utilities/array.hpp"
43 #include "utilities/debug.hpp"
44 #include "utilities/macros.hpp"
45 #include "utilities/exceptions.hpp"
47 #if INCLUDE_ALL_GCS
48 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
49 #include "gc_implementation/g1/concurrentMark.hpp"
50 #include "gc_implementation/g1/concurrentMarkThread.hpp"
51 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
52 #include "gc_implementation/g1/heapRegionRemSet.hpp"
53 #endif // INCLUDE_ALL_GCS
55 #if INCLUDE_NMT
56 #include "services/mallocSiteTable.hpp"
57 #include "services/memTracker.hpp"
58 #include "utilities/nativeCallStack.hpp"
59 #endif // INCLUDE_NMT
61 #include "compiler/compileBroker.hpp"
62 #include "jvmtifiles/jvmtiEnv.hpp"
63 #include "runtime/compilationPolicy.hpp"
65 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
67 #define SIZE_T_MAX_VALUE ((size_t) -1)
69 bool WhiteBox::_used = false;
71 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
72 return (jlong)(void*)JNIHandles::resolve(obj);
73 WB_END
75 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
76 return heapOopSize;
77 WB_END
79 WB_ENTRY(jint, WB_GetVMPageSize(JNIEnv* env, jobject o))
80 return os::vm_page_size();
81 WB_END
83 WB_ENTRY(jlong, WB_GetVMLargePageSize(JNIEnv* env, jobject o))
84 return os::large_page_size();
85 WB_END
87 class WBIsKlassAliveClosure : public KlassClosure {
88 Symbol* _name;
89 bool _found;
90 public:
91 WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
93 void do_klass(Klass* k) {
94 if (_found) return;
95 Symbol* ksym = k->name();
96 if (ksym->fast_compare(_name) == 0) {
97 _found = true;
98 }
99 }
101 bool found() const {
102 return _found;
103 }
104 };
106 WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
107 Handle h_name = JNIHandles::resolve(name);
108 if (h_name.is_null()) return false;
109 Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
110 TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
112 WBIsKlassAliveClosure closure(sym);
113 ClassLoaderDataGraph::classes_do(&closure);
115 return closure.found();
116 WB_END
118 WB_ENTRY(jboolean, WB_ClassKnownToNotExist(JNIEnv* env, jobject o, jobject loader, jstring name))
119 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
120 const char* class_name = env->GetStringUTFChars(name, NULL);
121 jboolean result = JVM_KnownToNotExist(env, loader, class_name);
122 env->ReleaseStringUTFChars(name, class_name);
123 return result;
124 WB_END
126 WB_ENTRY(jobjectArray, WB_GetLookupCacheURLs(JNIEnv* env, jobject o, jobject loader))
127 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
128 return JVM_GetResourceLookupCacheURLs(env, loader);
129 WB_END
131 WB_ENTRY(jintArray, WB_GetLookupCacheMatches(JNIEnv* env, jobject o, jobject loader, jstring name))
132 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
133 const char* resource_name = env->GetStringUTFChars(name, NULL);
134 jintArray result = JVM_GetResourceLookupCache(env, loader, resource_name);
136 env->ReleaseStringUTFChars(name, resource_name);
137 return result;
138 WB_END
140 WB_ENTRY(void, WB_AddToBootstrapClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
141 #if INCLUDE_JVMTI
142 ResourceMark rm;
143 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
144 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
145 jvmtiError err = jvmti_env->AddToBootstrapClassLoaderSearch(seg);
146 assert(err == JVMTI_ERROR_NONE, "must not fail");
147 #endif
148 }
149 WB_END
151 WB_ENTRY(void, WB_AddToSystemClassLoaderSearch(JNIEnv* env, jobject o, jstring segment)) {
152 #if INCLUDE_JVMTI
153 ResourceMark rm;
154 const char* seg = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(segment));
155 JvmtiEnv* jvmti_env = JvmtiEnv::create_a_jvmti(JVMTI_VERSION);
156 jvmtiError err = jvmti_env->AddToSystemClassLoaderSearch(seg);
157 assert(err == JVMTI_ERROR_NONE, "must not fail");
158 #endif
159 }
160 WB_END
162 #ifdef LINUX
163 #include "utilities/elfFile.hpp"
164 #include "osContainer_linux.hpp"
165 #endif
167 WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
168 return (jlong)Arguments::max_heap_for_compressed_oops();
169 }
170 WB_END
172 WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
173 CollectorPolicy * p = Universe::heap()->collector_policy();
174 gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap "
175 SIZE_FORMAT " Maximum heap " SIZE_FORMAT " Space alignment " SIZE_FORMAT " Heap alignment " SIZE_FORMAT,
176 p->min_heap_byte_size(), p->initial_heap_byte_size(), p->max_heap_byte_size(),
177 p->space_alignment(), p->heap_alignment());
178 }
179 WB_END
181 #ifndef PRODUCT
182 // Forward declaration
183 void TestReservedSpace_test();
184 void TestReserveMemorySpecial_test();
185 void TestVirtualSpace_test();
186 void TestMetaspaceAux_test();
187 #endif
189 WB_ENTRY(void, WB_RunMemoryUnitTests(JNIEnv* env, jobject o))
190 #ifndef PRODUCT
191 TestReservedSpace_test();
192 TestReserveMemorySpecial_test();
193 TestVirtualSpace_test();
194 TestMetaspaceAux_test();
195 #endif
196 WB_END
198 WB_ENTRY(void, WB_ReadFromNoaccessArea(JNIEnv* env, jobject o))
199 size_t granularity = os::vm_allocation_granularity();
200 ReservedHeapSpace rhs(100 * granularity, granularity, false, NULL);
201 VirtualSpace vs;
202 vs.initialize(rhs, 50 * granularity);
204 //Check if constraints are complied
205 if (!( UseCompressedOops && rhs.base() != NULL &&
206 Universe::narrow_oop_base() != NULL &&
207 Universe::narrow_oop_use_implicit_null_checks() )) {
208 tty->print_cr("WB_ReadFromNoaccessArea method is useless:\n "
209 "\tUseCompressedOops is %d\n"
210 "\trhs.base() is " PTR_FORMAT "\n"
211 "\tUniverse::narrow_oop_base() is " PTR_FORMAT "\n"
212 "\tUniverse::narrow_oop_use_implicit_null_checks() is %d",
213 UseCompressedOops,
214 rhs.base(),
215 Universe::narrow_oop_base(),
216 Universe::narrow_oop_use_implicit_null_checks());
217 return;
218 }
219 tty->print_cr("Reading from no access area... ");
220 tty->print_cr("*(vs.low_boundary() - rhs.noaccess_prefix() / 2 ) = %c",
221 *(vs.low_boundary() - rhs.noaccess_prefix() / 2 ));
222 WB_END
224 static jint wb_stress_virtual_space_resize(size_t reserved_space_size,
225 size_t magnitude, size_t iterations) {
226 size_t granularity = os::vm_allocation_granularity();
227 ReservedHeapSpace rhs(reserved_space_size * granularity, granularity, false, NULL);
228 VirtualSpace vs;
229 if (!vs.initialize(rhs, 0)) {
230 tty->print_cr("Failed to initialize VirtualSpace. Can't proceed.");
231 return 3;
232 }
234 long seed = os::random();
235 tty->print_cr("Random seed is %ld", seed);
236 os::init_random(seed);
238 for (size_t i = 0; i < iterations; i++) {
240 // Whether we will shrink or grow
241 bool shrink = os::random() % 2L == 0;
243 // Get random delta to resize virtual space
244 size_t delta = (size_t)os::random() % magnitude;
246 // If we are about to shrink virtual space below zero, then expand instead
247 if (shrink && vs.committed_size() < delta) {
248 shrink = false;
249 }
251 // Resizing by delta
252 if (shrink) {
253 vs.shrink_by(delta);
254 } else {
255 // If expanding fails expand_by will silently return false
256 vs.expand_by(delta, true);
257 }
258 }
259 return 0;
260 }
262 WB_ENTRY(jint, WB_StressVirtualSpaceResize(JNIEnv* env, jobject o,
263 jlong reserved_space_size, jlong magnitude, jlong iterations))
264 tty->print_cr("reservedSpaceSize=" JLONG_FORMAT ", magnitude=" JLONG_FORMAT ", "
265 "iterations=" JLONG_FORMAT "\n", reserved_space_size, magnitude,
266 iterations);
267 if (reserved_space_size < 0 || magnitude < 0 || iterations < 0) {
268 tty->print_cr("One of variables printed above is negative. Can't proceed.\n");
269 return 1;
270 }
272 // sizeof(size_t) depends on whether OS is 32bit or 64bit. sizeof(jlong) is
273 // always 8 byte. That's why we should avoid overflow in case of 32bit platform.
274 if (sizeof(size_t) < sizeof(jlong)) {
275 jlong size_t_max_value = (jlong) SIZE_T_MAX_VALUE;
276 if (reserved_space_size > size_t_max_value || magnitude > size_t_max_value
277 || iterations > size_t_max_value) {
278 tty->print_cr("One of variables printed above overflows size_t. Can't proceed.\n");
279 return 2;
280 }
281 }
283 return wb_stress_virtual_space_resize((size_t) reserved_space_size,
284 (size_t) magnitude, (size_t) iterations);
285 WB_END
287 WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
288 oop p = JNIHandles::resolve(obj);
289 #if INCLUDE_ALL_GCS
290 if (UseG1GC) {
291 G1CollectedHeap* g1 = G1CollectedHeap::heap();
292 const HeapRegion* hr = g1->heap_region_containing(p);
293 if (hr == NULL) {
294 return false;
295 }
296 return !(hr->is_young());
297 } else if (UseParallelGC) {
298 ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
299 return !psh->is_in_young(p);
300 }
301 #endif // INCLUDE_ALL_GCS
302 GenCollectedHeap* gch = GenCollectedHeap::heap();
303 return !gch->is_in_young(p);
304 WB_END
306 WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
307 oop p = JNIHandles::resolve(obj);
308 return p->size() * HeapWordSize;
309 WB_END
311 #if INCLUDE_ALL_GCS
312 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
313 G1CollectedHeap* g1 = G1CollectedHeap::heap();
314 oop result = JNIHandles::resolve(obj);
315 const HeapRegion* hr = g1->heap_region_containing(result);
316 return hr->isHumongous();
317 WB_END
319 WB_ENTRY(jlong, WB_G1NumMaxRegions(JNIEnv* env, jobject o))
320 G1CollectedHeap* g1 = G1CollectedHeap::heap();
321 size_t nr = g1->max_regions();
322 return (jlong)nr;
323 WB_END
325 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
326 G1CollectedHeap* g1 = G1CollectedHeap::heap();
327 size_t nr = g1->num_free_regions();
328 return (jlong)nr;
329 WB_END
331 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
332 G1CollectedHeap* g1 = G1CollectedHeap::heap();
333 return g1->concurrent_mark()->cmThread()->during_cycle();
334 WB_END
336 WB_ENTRY(jboolean, WB_G1StartMarkCycle(JNIEnv* env, jobject o))
337 G1CollectedHeap* g1h = G1CollectedHeap::heap();
338 if (!g1h->concurrent_mark()->cmThread()->during_cycle()) {
339 g1h->collect(GCCause::_wb_conc_mark);
340 return true;
341 }
342 return false;
343 WB_END
345 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
346 return (jint)HeapRegion::GrainBytes;
347 WB_END
349 WB_ENTRY(jobject, WB_G1AuxiliaryMemoryUsage(JNIEnv* env))
350 ResourceMark rm(THREAD);
351 G1CollectedHeap* g1h = G1CollectedHeap::heap();
352 MemoryUsage usage = g1h->get_auxiliary_data_memory_usage();
353 Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
354 return JNIHandles::make_local(env, h());
355 WB_END
356 #endif // INCLUDE_ALL_GCS
358 #if INCLUDE_NMT
359 // Alloc memory using the test memory type so that we can use that to see if
360 // NMT picks it up correctly
361 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
362 jlong addr = 0;
363 addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
364 return addr;
365 WB_END
367 // Alloc memory with pseudo call stack. The test can create psudo malloc
368 // allocation site to stress the malloc tracking.
369 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
370 address pc = (address)(size_t)pseudo_stack;
371 NativeCallStack stack(&pc, 1);
372 return (jlong)(uintptr_t)os::malloc(size, mtTest, stack);
373 WB_END
375 // Alloc memory with pseudo call stack and specific memory type.
376 WB_ENTRY(jlong, WB_NMTMallocWithPseudoStackAndType(JNIEnv* env, jobject o, jlong size, jint pseudo_stack, jint type))
377 address pc = (address)(size_t)pseudo_stack;
378 NativeCallStack stack(&pc, 1);
379 return (jlong)(uintptr_t)os::malloc(size, (MEMFLAGS)type, stack);
380 WB_END
382 // Free the memory allocated by NMTAllocTest
383 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
384 os::free((void*)(uintptr_t)mem, mtTest);
385 WB_END
387 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
388 jlong addr = 0;
390 addr = (jlong)(uintptr_t)os::reserve_memory(size);
391 MemTracker::record_virtual_memory_type((address)addr, mtTest);
393 return addr;
394 WB_END
397 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
398 os::commit_memory((char *)(uintptr_t)addr, size, !ExecMem);
399 MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
400 WB_END
402 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
403 os::uncommit_memory((char *)(uintptr_t)addr, size);
404 WB_END
406 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
407 os::release_memory((char *)(uintptr_t)addr, size);
408 WB_END
410 WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env))
411 return MemTracker::tracking_level() == NMT_detail;
412 WB_END
414 WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env))
415 // Test that we can downgrade NMT levels but not upgrade them.
416 if (MemTracker::tracking_level() == NMT_off) {
417 MemTracker::transition_to(NMT_off);
418 return MemTracker::tracking_level() == NMT_off;
419 } else {
420 assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking");
421 MemTracker::transition_to(NMT_summary);
422 assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now");
424 // Can't go to detail once NMT is set to summary.
425 MemTracker::transition_to(NMT_detail);
426 assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now");
428 // Shutdown sets tracking level to minimal.
429 MemTracker::shutdown();
430 assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now");
432 // Once the tracking level is minimal, we cannot increase to summary.
433 // The code ignores this request instead of asserting because if the malloc site
434 // table overflows in another thread, it tries to change the code to summary.
435 MemTracker::transition_to(NMT_summary);
436 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
438 // Really can never go up to detail, verify that the code would never do this.
439 MemTracker::transition_to(NMT_detail);
440 assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now");
441 return MemTracker::tracking_level() == NMT_minimal;
442 }
443 WB_END
445 WB_ENTRY(jint, WB_NMTGetHashSize(JNIEnv* env, jobject o))
446 int hash_size = MallocSiteTable::hash_buckets();
447 assert(hash_size > 0, "NMT hash_size should be > 0");
448 return (jint)hash_size;
449 WB_END
450 #endif // INCLUDE_NMT
452 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
453 assert(method != NULL, "method should not be null");
454 ThreadToNativeFromVM ttn(thread);
455 return env->FromReflectedMethod(method);
456 }
458 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
459 MutexLockerEx mu(Compile_lock);
460 CodeCache::mark_all_nmethods_for_deoptimization();
461 VM_Deoptimize op;
462 VMThread::execute(&op);
463 WB_END
465 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
466 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
467 int result = 0;
468 CHECK_JNI_EXCEPTION_(env, result);
469 MutexLockerEx mu(Compile_lock);
470 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
471 if (is_osr) {
472 result += mh->mark_osr_nmethods();
473 } else if (mh->code() != NULL) {
474 mh->code()->mark_for_deoptimization();
475 ++result;
476 }
477 result += CodeCache::mark_for_deoptimization(mh());
478 if (result > 0) {
479 VM_Deoptimize op;
480 VMThread::execute(&op);
481 }
482 return result;
483 WB_END
485 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
486 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
487 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
488 MutexLockerEx mu(Compile_lock);
489 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
490 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
491 if (code == NULL) {
492 return JNI_FALSE;
493 }
494 return (code->is_alive() && !code->is_marked_for_deoptimization());
495 WB_END
497 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
498 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
499 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
500 MutexLockerEx mu(Compile_lock);
501 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
502 if (is_osr) {
503 return CompilationPolicy::can_be_osr_compiled(mh, comp_level);
504 } else {
505 return CompilationPolicy::can_be_compiled(mh, comp_level);
506 }
507 WB_END
509 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
510 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
511 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
512 MutexLockerEx mu(Compile_lock);
513 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
514 return mh->queued_for_compilation();
515 WB_END
517 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
518 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
519 CHECK_JNI_EXCEPTION_(env, CompLevel_none);
520 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
521 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
522 return (code != NULL ? code->comp_level() : CompLevel_none);
523 WB_END
525 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr))
526 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
527 CHECK_JNI_EXCEPTION(env);
528 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
529 if (is_osr) {
530 mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox");
531 } else {
532 mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
533 }
534 WB_END
536 WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method))
537 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
538 CHECK_JNI_EXCEPTION_(env, InvocationEntryBci);
539 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
540 nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false);
541 return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci);
542 WB_END
544 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
545 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
546 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
547 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
548 bool result = mh->dont_inline();
549 mh->set_dont_inline(value == JNI_TRUE);
550 return result;
551 WB_END
553 WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level))
554 if (comp_level == CompLevel_any) {
555 return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
556 CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
557 } else {
558 return CompileBroker::queue_size(comp_level);
559 }
560 WB_END
562 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
563 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
564 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
565 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
566 bool result = mh->force_inline();
567 mh->set_force_inline(value == JNI_TRUE);
568 return result;
569 WB_END
571 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci))
572 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
573 CHECK_JNI_EXCEPTION_(env, JNI_FALSE);
574 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
575 nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
576 MutexLockerEx mu(Compile_lock);
577 return (mh->queued_for_compilation() || nm != NULL);
578 WB_END
580 class VM_WhiteBoxOperation : public VM_Operation {
581 public:
582 VM_WhiteBoxOperation() { }
583 VMOp_Type type() const { return VMOp_WhiteBoxOperation; }
584 bool allow_nested_vm_operations() const { return true; }
585 };
587 static AlwaysFalseClosure always_false;
589 class VM_WhiteBoxCleanMethodData : public VM_WhiteBoxOperation {
590 public:
591 VM_WhiteBoxCleanMethodData(MethodData* mdo) : _mdo(mdo) { }
592 void doit() {
593 _mdo->clean_method_data(&always_false);
594 }
595 private:
596 MethodData* _mdo;
597 };
599 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
600 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
601 CHECK_JNI_EXCEPTION(env);
602 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
603 MutexLockerEx mu(Compile_lock);
604 MethodData* mdo = mh->method_data();
605 MethodCounters* mcs = mh->method_counters();
607 if (mdo != NULL) {
608 mdo->init();
609 ResourceMark rm;
610 int arg_count = mdo->method()->size_of_parameters();
611 for (int i = 0; i < arg_count; i++) {
612 mdo->set_arg_modified(i, 0);
613 }
614 VM_WhiteBoxCleanMethodData op(mdo);
615 VMThread::execute(&op);
616 }
618 mh->clear_not_c1_compilable();
619 mh->clear_not_c2_compilable();
620 mh->clear_not_c2_osr_compilable();
621 NOT_PRODUCT(mh->set_compiled_invocation_count(0));
622 if (mcs != NULL) {
623 mcs->backedge_counter()->init();
624 mcs->invocation_counter()->init();
625 mcs->set_interpreter_invocation_count(0);
626 mcs->set_interpreter_throwout_count(0);
628 #ifdef TIERED
629 mcs->set_rate(0.0F);
630 mh->set_prev_event_count(0);
631 mh->set_prev_time(0);
632 #endif
633 }
634 WB_END
636 WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
637 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
638 CHECK_JNI_EXCEPTION(env);
639 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
641 MethodData* mdo = mh->method_data();
642 if (mdo == NULL) {
643 Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
644 mdo = mh->method_data();
645 }
646 mdo->init();
647 InvocationCounter* icnt = mdo->invocation_counter();
648 InvocationCounter* bcnt = mdo->backedge_counter();
649 // set i-counter according to AdvancedThresholdPolicy::is_method_profiled
650 // because SimpleThresholdPolicy::call_predicate_helper uses > in jdk8u, that's why we need to plus one.
651 icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold + 1);
652 bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold + 1);
653 WB_END
655 template <typename T>
656 static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) {
657 if (name == NULL) {
658 return false;
659 }
660 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
661 const char* flag_name = env->GetStringUTFChars(name, NULL);
662 bool result = (*TAt)(flag_name, value);
663 env->ReleaseStringUTFChars(name, flag_name);
664 return result;
665 }
667 template <typename T>
668 static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
669 if (name == NULL) {
670 return false;
671 }
672 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
673 const char* flag_name = env->GetStringUTFChars(name, NULL);
674 bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
675 env->ReleaseStringUTFChars(name, flag_name);
676 return result;
677 }
679 template <typename T>
680 static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
681 ResourceMark rm(thread);
682 jclass clazz = env->FindClass(name->as_C_string());
683 CHECK_JNI_EXCEPTION_(env, NULL);
684 jmethodID methodID = env->GetStaticMethodID(clazz,
685 vmSymbols::valueOf_name()->as_C_string(),
686 sig->as_C_string());
687 CHECK_JNI_EXCEPTION_(env, NULL);
688 jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
689 CHECK_JNI_EXCEPTION_(env, NULL);
690 return result;
691 }
693 static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
694 return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
695 }
696 static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
697 return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
698 }
699 static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
700 return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
701 }
702 /* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
703 return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
704 }*/
705 static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
706 return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
707 }
709 WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
710 bool result;
711 if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
712 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
713 return booleanBox(thread, env, result);
714 }
715 return NULL;
716 WB_END
718 WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
719 intx result;
720 if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
721 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
722 return longBox(thread, env, result);
723 }
724 return NULL;
725 WB_END
727 WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
728 uintx result;
729 if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
730 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
731 return longBox(thread, env, result);
732 }
733 return NULL;
734 WB_END
736 WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
737 uint64_t result;
738 if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
739 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
740 return longBox(thread, env, result);
741 }
742 return NULL;
743 WB_END
745 WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
746 double result;
747 if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
748 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
749 return doubleBox(thread, env, result);
750 }
751 return NULL;
752 WB_END
754 WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
755 ccstr ccstrResult;
756 if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
757 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
758 jstring result = env->NewStringUTF(ccstrResult);
759 CHECK_JNI_EXCEPTION_(env, NULL);
760 return result;
761 }
762 return NULL;
763 WB_END
765 WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
766 bool result = value == JNI_TRUE ? true : false;
767 SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
768 WB_END
770 WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
771 intx result = value;
772 SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
773 WB_END
775 WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
776 uintx result = value;
777 SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
778 WB_END
780 WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
781 uint64_t result = value;
782 SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
783 WB_END
785 WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
786 double result = value;
787 SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
788 WB_END
790 WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
791 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
792 const char* ccstrValue = (value == NULL) ? NULL : env->GetStringUTFChars(value, NULL);
793 ccstr ccstrResult = ccstrValue;
794 bool needFree;
795 {
796 ThreadInVMfromNative ttvfn(thread); // back to VM
797 needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
798 }
799 if (value != NULL) {
800 env->ReleaseStringUTFChars(value, ccstrValue);
801 }
802 if (needFree) {
803 FREE_C_HEAP_ARRAY(char, ccstrResult, mtInternal);
804 }
805 WB_END
808 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
809 ResourceMark rm(THREAD);
810 int len;
811 jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
812 return (StringTable::lookup(name, len) != NULL);
813 WB_END
815 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
816 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
817 Universe::heap()->collect(GCCause::_last_ditch_collection);
818 #if INCLUDE_ALL_GCS
819 if (UseG1GC) {
820 // Needs to be cleared explicitly for G1
821 Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(false);
822 }
823 #endif // INCLUDE_ALL_GCS
824 WB_END
826 WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
827 Universe::heap()->collect(GCCause::_wb_young_gc);
828 WB_END
830 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
831 // static+volatile in order to force the read to happen
832 // (not be eliminated by the compiler)
833 static char c;
834 static volatile char* p;
836 p = os::reserve_memory(os::vm_allocation_granularity(), NULL, 0);
837 if (p == NULL) {
838 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Failed to reserve memory");
839 }
841 c = *p;
842 WB_END
844 WB_ENTRY(jstring, WB_GetCPUFeatures(JNIEnv* env, jobject o))
845 const char* cpu_features = VM_Version::cpu_features();
846 ThreadToNativeFromVM ttn(thread);
847 jstring features_string = env->NewStringUTF(cpu_features);
849 CHECK_JNI_EXCEPTION_(env, NULL);
851 return features_string;
852 WB_END
855 WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr))
856 ResourceMark rm(THREAD);
857 jmethodID jmid = reflected_method_to_jmid(thread, env, method);
858 CHECK_JNI_EXCEPTION_(env, NULL);
859 methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
860 nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code();
861 jobjectArray result = NULL;
862 if (code == NULL) {
863 return result;
864 }
865 int insts_size = code->insts_size();
867 ThreadToNativeFromVM ttn(thread);
868 jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string());
869 CHECK_JNI_EXCEPTION_(env, NULL);
870 result = env->NewObjectArray(3, clazz, NULL);
871 if (result == NULL) {
872 return result;
873 }
875 jobject level = integerBox(thread, env, code->comp_level());
876 CHECK_JNI_EXCEPTION_(env, NULL);
877 env->SetObjectArrayElement(result, 0, level);
879 jobject id = integerBox(thread, env, code->compile_id());
880 CHECK_JNI_EXCEPTION_(env, NULL);
881 env->SetObjectArrayElement(result, 1, id);
883 jbyteArray insts = env->NewByteArray(insts_size);
884 CHECK_JNI_EXCEPTION_(env, NULL);
885 env->SetByteArrayRegion(insts, 0, insts_size, (jbyte*) code->insts_begin());
886 env->SetObjectArrayElement(result, 2, insts);
888 return result;
889 WB_END
892 int WhiteBox::array_bytes_to_length(size_t bytes) {
893 return Array<u1>::bytes_to_length(bytes);
894 }
896 WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
897 if (size < 0) {
898 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
899 err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
900 }
902 oop class_loader_oop = JNIHandles::resolve(class_loader);
903 ClassLoaderData* cld = class_loader_oop != NULL
904 ? java_lang_ClassLoader::loader_data(class_loader_oop)
905 : ClassLoaderData::the_null_class_loader_data();
907 void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
909 return (jlong)(uintptr_t)metadata;
910 WB_END
912 WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
913 oop class_loader_oop = JNIHandles::resolve(class_loader);
914 ClassLoaderData* cld = class_loader_oop != NULL
915 ? java_lang_ClassLoader::loader_data(class_loader_oop)
916 : ClassLoaderData::the_null_class_loader_data();
918 MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
919 WB_END
921 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
922 if (inc < 0) {
923 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
924 err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc));
925 }
927 jlong max_size_t = (jlong) ((size_t) -1);
928 if (inc > max_size_t) {
929 THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
930 err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc));
931 }
933 size_t new_cap_until_GC = 0;
934 size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment());
935 bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC);
936 if (!success) {
937 THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(),
938 "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC "
939 "due to contention with another thread");
940 }
941 return (jlong) new_cap_until_GC;
942 WB_END
944 WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb))
945 return (jlong) MetaspaceGC::capacity_until_GC();
946 WB_END
948 WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
949 return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
950 WB_END
952 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
953 oop obj_oop = JNIHandles::resolve(obj);
954 return (jboolean) obj_oop->mark()->has_monitor();
955 WB_END
957 WB_ENTRY(void, WB_ForceSafepoint(JNIEnv* env, jobject wb))
958 VM_ForceSafepoint force_safepoint_op;
959 VMThread::execute(&force_safepoint_op);
960 WB_END
962 //Some convenience methods to deal with objects from java
963 int WhiteBox::offset_for_field(const char* field_name, oop object,
964 Symbol* signature_symbol) {
965 assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
966 Thread* THREAD = Thread::current();
968 //Get the class of our object
969 Klass* arg_klass = object->klass();
970 //Turn it into an instance-klass
971 InstanceKlass* ik = InstanceKlass::cast(arg_klass);
973 //Create symbols to look for in the class
974 TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
975 THREAD);
977 //To be filled in with an offset of the field we're looking for
978 fieldDescriptor fd;
980 Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
981 if (res == NULL) {
982 tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
983 name_symbol->as_C_string());
984 vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class");
985 }
987 //fetch the field at the offset we've found
988 int dest_offset = fd.offset();
990 return dest_offset;
991 }
994 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
995 int offset = offset_for_field(field_name, object,
996 vmSymbols::string_signature());
997 oop string = object->obj_field(offset);
998 if (string == NULL) {
999 return NULL;
1000 }
1001 const char* ret = java_lang_String::as_utf8_string(string);
1002 return ret;
1003 }
1005 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
1006 int offset =
1007 offset_for_field(field_name, object, vmSymbols::bool_signature());
1008 bool ret = (object->bool_field(offset) == JNI_TRUE);
1009 return ret;
1010 }
1012 void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count) {
1013 ResourceMark rm;
1014 ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
1016 // one by one registration natives for exception catching
1017 jclass no_such_method_error_klass = env->FindClass(vmSymbols::java_lang_NoSuchMethodError()->as_C_string());
1018 CHECK_JNI_EXCEPTION(env);
1019 for (int i = 0, n = method_count; i < n; ++i) {
1020 // Skip dummy entries
1021 if (method_array[i].fnPtr == NULL) continue;
1022 if (env->RegisterNatives(wbclass, &method_array[i], 1) != 0) {
1023 jthrowable throwable_obj = env->ExceptionOccurred();
1024 if (throwable_obj != NULL) {
1025 env->ExceptionClear();
1026 if (env->IsInstanceOf(throwable_obj, no_such_method_error_klass)) {
1027 // NoSuchMethodError is thrown when a method can't be found or a method is not native.
1028 // Ignoring the exception since it is not preventing use of other WhiteBox methods.
1029 tty->print_cr("Warning: 'NoSuchMethodError' on register of sun.hotspot.WhiteBox::%s%s",
1030 method_array[i].name, method_array[i].signature);
1031 }
1032 } else {
1033 // Registration failed unexpectedly.
1034 tty->print_cr("Warning: unexpected error on register of sun.hotspot.WhiteBox::%s%s. All methods will be unregistered",
1035 method_array[i].name, method_array[i].signature);
1036 env->UnregisterNatives(wbclass);
1037 break;
1038 }
1039 }
1040 }
1041 }
1043 // Checks that the library libfile has the noexecstack bit set.
1044 WB_ENTRY(jboolean, WB_CheckLibSpecifiesNoexecstack(JNIEnv* env, jobject o, jstring libfile))
1045 jboolean ret = false;
1046 #ifdef LINUX
1047 // Can't be in VM when we call JNI.
1048 ThreadToNativeFromVM ttnfv(thread);
1049 const char* lf = env->GetStringUTFChars(libfile, NULL);
1050 CHECK_JNI_EXCEPTION_(env, 0);
1051 ElfFile ef(lf);
1052 ret = (jboolean) ef.specifies_noexecstack();
1053 env->ReleaseStringUTFChars(libfile, lf);
1054 #endif
1055 return ret;
1056 WB_END
1058 WB_ENTRY(jboolean, WB_IsContainerized(JNIEnv* env, jobject o))
1059 LINUX_ONLY(return OSContainer::is_containerized();)
1060 return false;
1061 WB_END
1063 WB_ENTRY(void, WB_PrintOsInfo(JNIEnv* env, jobject o))
1064 os::print_os_info(tty);
1065 WB_END
1067 #define CC (char*)
1069 static JNINativeMethod methods[] = {
1070 {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress },
1071 {CC"getObjectSize", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize },
1072 {CC"isObjectInOldGen", CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen },
1073 {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize },
1074 {CC"getVMPageSize", CC"()I", (void*)&WB_GetVMPageSize },
1075 {CC"getVMLargePageSize", CC"()J", (void*)&WB_GetVMLargePageSize},
1076 {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive },
1077 {CC"classKnownToNotExist",
1078 CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)Z",(void*)&WB_ClassKnownToNotExist},
1079 {CC"getLookupCacheURLs", CC"(Ljava/lang/ClassLoader;)[Ljava/net/URL;", (void*)&WB_GetLookupCacheURLs},
1080 {CC"getLookupCacheMatches", CC"(Ljava/lang/ClassLoader;Ljava/lang/String;)[I",
1081 (void*)&WB_GetLookupCacheMatches},
1082 {CC"parseCommandLine",
1083 CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
1084 (void*) &WB_ParseCommandLine
1085 },
1086 {CC"addToBootstrapClassLoaderSearch", CC"(Ljava/lang/String;)V",
1087 (void*)&WB_AddToBootstrapClassLoaderSearch},
1088 {CC"addToSystemClassLoaderSearch", CC"(Ljava/lang/String;)V",
1089 (void*)&WB_AddToSystemClassLoaderSearch},
1090 {CC"getCompressedOopsMaxHeapSize", CC"()J",
1091 (void*)&WB_GetCompressedOopsMaxHeapSize},
1092 {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
1093 {CC"runMemoryUnitTests", CC"()V", (void*)&WB_RunMemoryUnitTests},
1094 {CC"readFromNoaccessArea",CC"()V", (void*)&WB_ReadFromNoaccessArea},
1095 {CC"stressVirtualSpaceResize",CC"(JJJ)I", (void*)&WB_StressVirtualSpaceResize},
1096 {CC"isSharedClass", CC"(Ljava/lang/Class;)Z", (void*)&WB_IsSharedClass },
1097 #if INCLUDE_ALL_GCS
1098 {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
1099 {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous },
1100 {CC"g1NumMaxRegions", CC"()J", (void*)&WB_G1NumMaxRegions },
1101 {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions },
1102 {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize },
1103 {CC"g1StartConcMarkCycle", CC"()Z", (void*)&WB_G1StartMarkCycle },
1104 {CC"g1AuxiliaryMemoryUsage", CC"()Ljava/lang/management/MemoryUsage;",
1105 (void*)&WB_G1AuxiliaryMemoryUsage },
1106 #endif // INCLUDE_ALL_GCS
1107 #if INCLUDE_NMT
1108 {CC"NMTMalloc", CC"(J)J", (void*)&WB_NMTMalloc },
1109 {CC"NMTMallocWithPseudoStack", CC"(JI)J", (void*)&WB_NMTMallocWithPseudoStack},
1110 {CC"NMTMallocWithPseudoStackAndType", CC"(JII)J", (void*)&WB_NMTMallocWithPseudoStackAndType},
1111 {CC"NMTFree", CC"(J)V", (void*)&WB_NMTFree },
1112 {CC"NMTReserveMemory", CC"(J)J", (void*)&WB_NMTReserveMemory },
1113 {CC"NMTCommitMemory", CC"(JJ)V", (void*)&WB_NMTCommitMemory },
1114 {CC"NMTUncommitMemory", CC"(JJ)V", (void*)&WB_NMTUncommitMemory },
1115 {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory },
1116 {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported},
1117 {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel},
1118 {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize },
1119 #endif // INCLUDE_NMT
1120 {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll },
1121 {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I",
1122 (void*)&WB_DeoptimizeMethod },
1123 {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;Z)Z",
1124 (void*)&WB_IsMethodCompiled },
1125 {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z",
1126 (void*)&WB_IsMethodCompilable},
1127 {CC"isMethodQueuedForCompilation",
1128 CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation},
1129 {CC"makeMethodNotCompilable",
1130 CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable},
1131 {CC"testSetDontInlineMethod",
1132 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod},
1133 {CC"getMethodCompilationLevel",
1134 CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel},
1135 {CC"getMethodEntryBci",
1136 CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci},
1137 {CC"getCompileQueueSize",
1138 CC"(I)I", (void*)&WB_GetCompileQueueSize},
1139 {CC"testSetForceInlineMethod",
1140 CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod},
1141 {CC"enqueueMethodForCompilation",
1142 CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation},
1143 {CC"clearMethodState",
1144 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState},
1145 {CC"markMethodProfiled",
1146 CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_MarkMethodProfiled},
1147 {CC"setBooleanVMFlag", CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
1148 {CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
1149 {CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
1150 {CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
1151 {CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
1152 {CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
1153 (void*)&WB_SetStringVMFlag},
1154 {CC"getBooleanVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
1155 (void*)&WB_GetBooleanVMFlag},
1156 {CC"getIntxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1157 (void*)&WB_GetIntxVMFlag},
1158 {CC"getUintxVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1159 (void*)&WB_GetUintxVMFlag},
1160 {CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
1161 (void*)&WB_GetUint64VMFlag},
1162 {CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
1163 (void*)&WB_GetDoubleVMFlag},
1164 {CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
1165 (void*)&WB_GetStringVMFlag},
1166 {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable },
1167 {CC"fullGC", CC"()V", (void*)&WB_FullGC },
1168 {CC"youngGC", CC"()V", (void*)&WB_YoungGC },
1169 {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory },
1170 {CC"allocateMetaspace",
1171 CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace },
1172 {CC"freeMetaspace",
1173 CC"(Ljava/lang/ClassLoader;JJ)V", (void*)&WB_FreeMetaspace },
1174 {CC"incMetaspaceCapacityUntilGC", CC"(J)J", (void*)&WB_IncMetaspaceCapacityUntilGC },
1175 {CC"metaspaceCapacityUntilGC", CC"()J", (void*)&WB_MetaspaceCapacityUntilGC },
1176 {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures },
1177 {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
1178 (void*)&WB_GetNMethod },
1179 {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
1180 {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint },
1181 {CC"checkLibSpecifiesNoexecstack", CC"(Ljava/lang/String;)Z",
1182 (void*)&WB_CheckLibSpecifiesNoexecstack},
1183 {CC"isContainerized", CC"()Z", (void*)&WB_IsContainerized },
1184 {CC"printOsInfo", CC"()V", (void*)&WB_PrintOsInfo },
1185 };
1187 #undef CC
1189 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
1190 {
1191 if (WhiteBoxAPI) {
1192 // Make sure that wbclass is loaded by the null classloader
1193 instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
1194 Handle loader(ikh->class_loader());
1195 if (loader.is_null()) {
1196 WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));
1197 WhiteBox::register_extended(env, wbclass, thread);
1198 WhiteBox::set_used();
1199 }
1200 }
1201 }
1202 JVM_END