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