src/share/vm/prims/whitebox.cpp

Mon, 29 Apr 2013 16:13:57 -0400

author
hseigel
date
Mon, 29 Apr 2013 16:13:57 -0400
changeset 4987
f258c5828eb8
parent 4954
2a9d97b57920
child 4989
f32b6c267d2e
permissions
-rw-r--r--

8011773: Some tests on Interned String crashed JVM with OOM
Summary: Instead of terminating the VM, throw OutOfMemoryError exceptions.
Reviewed-by: coleenp, dholmes

     1 /*
     2  * Copyright (c) 2012, 2013, 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/universe.hpp"
    28 #include "oops/oop.inline.hpp"
    30 #include "classfile/symbolTable.hpp"
    31 #include "classfile/classLoaderData.hpp"
    33 #include "prims/whitebox.hpp"
    34 #include "prims/wbtestmethods/parserTests.hpp"
    36 #include "runtime/interfaceSupport.hpp"
    37 #include "runtime/os.hpp"
    38 #include "utilities/debug.hpp"
    39 #include "utilities/macros.hpp"
    41 #if INCLUDE_ALL_GCS
    42 #include "gc_implementation/g1/concurrentMark.hpp"
    43 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
    44 #include "gc_implementation/g1/heapRegionRemSet.hpp"
    45 #endif // INCLUDE_ALL_GCS
    47 #ifdef INCLUDE_NMT
    48 #include "services/memTracker.hpp"
    49 #endif // INCLUDE_NMT
    51 #include "compiler/compileBroker.hpp"
    52 #include "runtime/compilationPolicy.hpp"
    54 bool WhiteBox::_used = false;
    56 WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj))
    57   return (jlong)(void*)JNIHandles::resolve(obj);
    58 WB_END
    60 WB_ENTRY(jint, WB_GetHeapOopSize(JNIEnv* env, jobject o))
    61   return heapOopSize;
    62 WB_END
    65 class WBIsKlassAliveClosure : public KlassClosure {
    66     Symbol* _name;
    67     bool _found;
    68 public:
    69     WBIsKlassAliveClosure(Symbol* name) : _name(name), _found(false) {}
    71     void do_klass(Klass* k) {
    72       if (_found) return;
    73       Symbol* ksym = k->name();
    74       if (ksym->fast_compare(_name) == 0) {
    75         _found = true;
    76       }
    77     }
    79     bool found() const {
    80         return _found;
    81     }
    82 };
    84 WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
    85   Handle h_name = JNIHandles::resolve(name);
    86   if (h_name.is_null()) return false;
    87   Symbol* sym = java_lang_String::as_symbol(h_name, CHECK_false);
    88   TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return
    90   WBIsKlassAliveClosure closure(sym);
    91   ClassLoaderDataGraph::classes_do(&closure);
    93   return closure.found();
    94 WB_END
    96 #if INCLUDE_ALL_GCS
    97 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
    98   G1CollectedHeap* g1 = G1CollectedHeap::heap();
    99   oop result = JNIHandles::resolve(obj);
   100   const HeapRegion* hr = g1->heap_region_containing(result);
   101   return hr->isHumongous();
   102 WB_END
   104 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
   105   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   106   size_t nr = g1->free_regions();
   107   return (jlong)nr;
   108 WB_END
   110 WB_ENTRY(jboolean, WB_G1InConcurrentMark(JNIEnv* env, jobject o))
   111   G1CollectedHeap* g1 = G1CollectedHeap::heap();
   112   ConcurrentMark* cm = g1->concurrent_mark();
   113   return cm->concurrent_marking_in_progress();
   114 WB_END
   116 WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o))
   117   return (jint)HeapRegion::GrainBytes;
   118 WB_END
   119 #endif // INCLUDE_ALL_GCS
   121 #ifdef INCLUDE_NMT
   122 // Alloc memory using the test memory type so that we can use that to see if
   123 // NMT picks it up correctly
   124 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
   125   jlong addr = 0;
   127   if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
   128     addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
   129   }
   131   return addr;
   132 WB_END
   134 // Free the memory allocated by NMTAllocTest
   135 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
   136   os::free((void*)(uintptr_t)mem, mtTest);
   137 WB_END
   139 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
   140   jlong addr = 0;
   142   if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
   143     addr = (jlong)(uintptr_t)os::reserve_memory(size);
   144     MemTracker::record_virtual_memory_type((address)addr, mtTest);
   145   }
   147   return addr;
   148 WB_END
   151 WB_ENTRY(void, WB_NMTCommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
   152   os::commit_memory((char *)(uintptr_t)addr, size);
   153   MemTracker::record_virtual_memory_type((address)(uintptr_t)addr, mtTest);
   154 WB_END
   156 WB_ENTRY(void, WB_NMTUncommitMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
   157   os::uncommit_memory((char *)(uintptr_t)addr, size);
   158 WB_END
   160 WB_ENTRY(void, WB_NMTReleaseMemory(JNIEnv* env, jobject o, jlong addr, jlong size))
   161   os::release_memory((char *)(uintptr_t)addr, size);
   162 WB_END
   164 // Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
   165 WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env))
   167   if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
   168     return false;
   169   }
   171   return MemTracker::wbtest_wait_for_data_merge();
   172 WB_END
   174 #endif // INCLUDE_NMT
   176 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
   177   assert(method != NULL, "method should not be null");
   178   ThreadToNativeFromVM ttn(thread);
   179   return env->FromReflectedMethod(method);
   180 }
   182 WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o))
   183   MutexLockerEx mu(Compile_lock);
   184   CodeCache::mark_all_nmethods_for_deoptimization();
   185   VM_Deoptimize op;
   186   VMThread::execute(&op);
   187 WB_END
   189 WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method))
   190   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   191   MutexLockerEx mu(Compile_lock);
   192   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   193   int result = 0;
   194   nmethod* code = mh->code();
   195   if (code != NULL) {
   196     code->mark_for_deoptimization();
   197     ++result;
   198   }
   199   result += CodeCache::mark_for_deoptimization(mh());
   200   if (result > 0) {
   201     VM_Deoptimize op;
   202     VMThread::execute(&op);
   203   }
   204   return result;
   205 WB_END
   207 WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method))
   208   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   209   MutexLockerEx mu(Compile_lock);
   210   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   211   nmethod* code = mh->code();
   212   if (code == NULL) {
   213     return JNI_FALSE;
   214   }
   215   return (code->is_alive() && !code->is_marked_for_deoptimization());
   216 WB_END
   218 WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
   219   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   220   MutexLockerEx mu(Compile_lock);
   221   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   222   return CompilationPolicy::can_be_compiled(mh, comp_level);
   223 WB_END
   225 WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method))
   226   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   227   MutexLockerEx mu(Compile_lock);
   228   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   229   return mh->queued_for_compilation();
   230 WB_END
   232 WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method))
   233   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   234   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   235   nmethod* code = mh->code();
   236   return (code != NULL ? code->comp_level() : CompLevel_none);
   237 WB_END
   240 WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level))
   241   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   242   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   243   mh->set_not_compilable(comp_level, true /* report */, "WhiteBox");
   244 WB_END
   246 WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
   247   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   248   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   249   bool result = mh->dont_inline();
   250   mh->set_dont_inline(value == JNI_TRUE);
   251   return result;
   252 WB_END
   254 WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o))
   255   return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ +
   256          CompileBroker::queue_size(CompLevel_full_profile) /* C1 */;
   257 WB_END
   260 WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value))
   261   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   262   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   263   bool result = mh->force_inline();
   264   mh->set_force_inline(value == JNI_TRUE);
   265   return result;
   266 WB_END
   268 WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level))
   269   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   270   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   271   nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD);
   272   MutexLockerEx mu(Compile_lock);
   273   return (mh->queued_for_compilation() || nm != NULL);
   274 WB_END
   276 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
   277   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   278   methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
   279   MutexLockerEx mu(Compile_lock);
   280   MethodData* mdo = mh->method_data();
   281   MethodCounters* mcs = mh->method_counters();
   283   if (mdo != NULL) {
   284     mdo->init();
   285     ResourceMark rm;
   286     int arg_count = mdo->method()->size_of_parameters();
   287     for (int i = 0; i < arg_count; i++) {
   288       mdo->set_arg_modified(i, 0);
   289     }
   290   }
   292   mh->clear_not_c1_compilable();
   293   mh->clear_not_c2_compilable();
   294   mh->clear_not_c2_osr_compilable();
   295   NOT_PRODUCT(mh->set_compiled_invocation_count(0));
   296   if (mcs != NULL) {
   297     mcs->backedge_counter()->init();
   298     mcs->invocation_counter()->init();
   299     mcs->set_interpreter_invocation_count(0);
   300     mcs->set_interpreter_throwout_count(0);
   302 #ifdef TIERED
   303     mcs->set_rate(0.0F);
   304     mh->set_prev_event_count(0, THREAD);
   305     mh->set_prev_time(0, THREAD);
   306 #endif
   307   }
   308 WB_END
   310 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
   311   ResourceMark rm(THREAD);
   312   int len;
   313   jchar* name = java_lang_String::as_unicode_string(JNIHandles::resolve(javaString), len, CHECK_false);
   314   return (StringTable::lookup(name, len) != NULL);
   315 WB_END
   318 WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o))
   319   Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true);
   320   Universe::heap()->collect(GCCause::_last_ditch_collection);
   321 WB_END
   323 //Some convenience methods to deal with objects from java
   324 int WhiteBox::offset_for_field(const char* field_name, oop object,
   325     Symbol* signature_symbol) {
   326   assert(field_name != NULL && strlen(field_name) > 0, "Field name not valid");
   327   Thread* THREAD = Thread::current();
   329   //Get the class of our object
   330   Klass* arg_klass = object->klass();
   331   //Turn it into an instance-klass
   332   InstanceKlass* ik = InstanceKlass::cast(arg_klass);
   334   //Create symbols to look for in the class
   335   TempNewSymbol name_symbol = SymbolTable::lookup(field_name, (int) strlen(field_name),
   336       THREAD);
   338   //To be filled in with an offset of the field we're looking for
   339   fieldDescriptor fd;
   341   Klass* res = ik->find_field(name_symbol, signature_symbol, &fd);
   342   if (res == NULL) {
   343     tty->print_cr("Invalid layout of %s at %s", ik->external_name(),
   344         name_symbol->as_C_string());
   345     fatal("Invalid layout of preloaded class");
   346   }
   348   //fetch the field at the offset we've found
   349   int dest_offset = fd.offset();
   351   return dest_offset;
   352 }
   355 const char* WhiteBox::lookup_jstring(const char* field_name, oop object) {
   356   int offset = offset_for_field(field_name, object,
   357       vmSymbols::string_signature());
   358   oop string = object->obj_field(offset);
   359   if (string == NULL) {
   360     return NULL;
   361   }
   362   const char* ret = java_lang_String::as_utf8_string(string);
   363   return ret;
   364 }
   366 bool WhiteBox::lookup_bool(const char* field_name, oop object) {
   367   int offset =
   368       offset_for_field(field_name, object, vmSymbols::bool_signature());
   369   bool ret = (object->bool_field(offset) == JNI_TRUE);
   370   return ret;
   371 }
   374 #define CC (char*)
   376 static JNINativeMethod methods[] = {
   377   {CC"getObjectAddress",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
   378   {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
   379   {CC"isClassAlive0",      CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
   380   {CC"parseCommandLine",
   381       CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
   382       (void*) &WB_ParseCommandLine
   383   },
   384 #if INCLUDE_ALL_GCS
   385   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
   386   {CC"g1IsHumongous",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
   387   {CC"g1NumFreeRegions",   CC"()J",                   (void*)&WB_G1NumFreeRegions  },
   388   {CC"g1RegionSize",       CC"()I",                   (void*)&WB_G1RegionSize      },
   389 #endif // INCLUDE_ALL_GCS
   390 #ifdef INCLUDE_NMT
   391   {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
   392   {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
   393   {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
   394   {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
   395   {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
   396   {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
   397   {CC"NMTWaitForDataMerge", CC"()Z",                  (void*)&WB_NMTWaitForDataMerge},
   398 #endif // INCLUDE_NMT
   399   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
   400   {CC"deoptimizeMethod",   CC"(Ljava/lang/reflect/Executable;)I",
   401                                                       (void*)&WB_DeoptimizeMethod  },
   402   {CC"isMethodCompiled",   CC"(Ljava/lang/reflect/Executable;)Z",
   403                                                       (void*)&WB_IsMethodCompiled  },
   404   {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;I)Z",
   405                                                       (void*)&WB_IsMethodCompilable},
   406   {CC"isMethodQueuedForCompilation",
   407       CC"(Ljava/lang/reflect/Executable;)Z",          (void*)&WB_IsMethodQueuedForCompilation},
   408   {CC"makeMethodNotCompilable",
   409       CC"(Ljava/lang/reflect/Executable;I)V",         (void*)&WB_MakeMethodNotCompilable},
   410   {CC"testSetDontInlineMethod",
   411       CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetDontInlineMethod},
   412   {CC"getMethodCompilationLevel",
   413       CC"(Ljava/lang/reflect/Executable;)I",          (void*)&WB_GetMethodCompilationLevel},
   414   {CC"getCompileQueuesSize",
   415       CC"()I",                                        (void*)&WB_GetCompileQueuesSize},
   416   {CC"testSetForceInlineMethod",
   417       CC"(Ljava/lang/reflect/Executable;Z)Z",         (void*)&WB_TestSetForceInlineMethod},
   418   {CC"enqueueMethodForCompilation",
   419       CC"(Ljava/lang/reflect/Executable;I)Z",         (void*)&WB_EnqueueMethodForCompilation},
   420   {CC"clearMethodState",
   421       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
   422   {CC"isInStringTable",   CC"(Ljava/lang/String;)Z",  (void*)&WB_IsInStringTable  },
   423   {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
   424 };
   426 #undef CC
   428 JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
   429   {
   430     if (WhiteBoxAPI) {
   431       // Make sure that wbclass is loaded by the null classloader
   432       instanceKlassHandle ikh = instanceKlassHandle(JNIHandles::resolve(wbclass)->klass());
   433       Handle loader(ikh->class_loader());
   434       if (loader.is_null()) {
   435         ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
   436         jint result = env->RegisterNatives(wbclass, methods, sizeof(methods)/sizeof(methods[0]));
   437         if (result == 0) {
   438           WhiteBox::set_used();
   439         }
   440       }
   441     }
   442   }
   443 JVM_END

mercurial