src/share/vm/runtime/interfaceSupport.cpp

Mon, 03 Jan 2011 14:09:11 -0500

author
coleenp
date
Mon, 03 Jan 2011 14:09:11 -0500
changeset 2418
36c186bcc085
parent 2314
f95d63e2154a
child 2497
3582bf76420e
permissions
-rw-r--r--

6302804: Hotspot VM dies ungraceful death when C heap is exhausted in various places.
Summary: enhance the error reporting mechanism to help user to fix the problem rather than making it look like a VM error.
Reviewed-by: kvn, kamg

     1 /*
     2  * Copyright (c) 1997, 2010, 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"
    26 #include "gc_implementation/shared/markSweep.hpp"
    27 #include "gc_interface/collectedHeap.hpp"
    28 #include "gc_interface/collectedHeap.inline.hpp"
    29 #include "memory/genCollectedHeap.hpp"
    30 #include "memory/resourceArea.hpp"
    31 #include "runtime/init.hpp"
    32 #include "runtime/interfaceSupport.hpp"
    33 #include "runtime/threadLocalStorage.hpp"
    34 #include "runtime/vframe.hpp"
    35 #include "utilities/preserveException.hpp"
    38 // Implementation of InterfaceSupport
    40 #ifdef ASSERT
    42 long InterfaceSupport::_number_of_calls       = 0;
    43 long InterfaceSupport::_scavenge_alot_counter = 1;
    44 long InterfaceSupport::_fullgc_alot_counter   = 1;
    45 long InterfaceSupport::_fullgc_alot_invocation = 0;
    47 Histogram* RuntimeHistogram;
    49 RuntimeHistogramElement::RuntimeHistogramElement(const char* elementName) {
    50   static volatile jint RuntimeHistogram_lock = 0;
    51   _name = elementName;
    52   uintx count = 0;
    54   while (Atomic::cmpxchg(1, &RuntimeHistogram_lock, 0) != 0) {
    55     while (OrderAccess::load_acquire(&RuntimeHistogram_lock) != 0) {
    56       count +=1;
    57       if ( (WarnOnStalledSpinLock > 0)
    58         && (count % WarnOnStalledSpinLock == 0)) {
    59         warning("RuntimeHistogram_lock seems to be stalled");
    60       }
    61     }
    62   }
    64   if (RuntimeHistogram == NULL) {
    65     RuntimeHistogram = new Histogram("VM Runtime Call Counts",200);
    66   }
    68   RuntimeHistogram->add_element(this);
    69   Atomic::dec(&RuntimeHistogram_lock);
    70 }
    72 void InterfaceSupport::trace(const char* result_type, const char* header) {
    73   tty->print_cr("%6d  %s", _number_of_calls, header);
    74 }
    76 void InterfaceSupport::gc_alot() {
    77   Thread *thread = Thread::current();
    78   if (!thread->is_Java_thread()) return; // Avoid concurrent calls
    79   // Check for new, not quite initialized thread. A thread in new mode cannot initiate a GC.
    80   JavaThread *current_thread = (JavaThread *)thread;
    81   if (current_thread->active_handles() == NULL) return;
    83   // Short-circuit any possible re-entrant gc-a-lot attempt
    84   if (thread->skip_gcalot()) return;
    86   if (is_init_completed()) {
    88     if (++_fullgc_alot_invocation < FullGCALotStart) {
    89       return;
    90     }
    92     // Use this line if you want to block at a specific point,
    93     // e.g. one number_of_calls/scavenge/gc before you got into problems
    94     if (FullGCALot) _fullgc_alot_counter--;
    96     // Check if we should force a full gc
    97     if (_fullgc_alot_counter == 0) {
    98       // Release dummy so objects are forced to move
    99       if (!Universe::release_fullgc_alot_dummy()) {
   100         warning("FullGCALot: Unable to release more dummies at bottom of heap");
   101       }
   102       HandleMark hm(thread);
   103       Universe::heap()->collect(GCCause::_full_gc_alot);
   104       unsigned int invocations = Universe::heap()->total_full_collections();
   105       // Compute new interval
   106       if (FullGCALotInterval > 1) {
   107         _fullgc_alot_counter = 1+(long)((double)FullGCALotInterval*os::random()/(max_jint+1.0));
   108         if (PrintGCDetails && Verbose) {
   109           tty->print_cr("Full gc no: %u\tInterval: %d", invocations,
   110                         _fullgc_alot_counter);
   111         }
   112       } else {
   113         _fullgc_alot_counter = 1;
   114       }
   115       // Print progress message
   116       if (invocations % 100 == 0) {
   117         if (PrintGCDetails && Verbose) tty->print_cr("Full gc no: %u", invocations);
   118       }
   119     } else {
   120       if (ScavengeALot) _scavenge_alot_counter--;
   121       // Check if we should force a scavenge
   122       if (_scavenge_alot_counter == 0) {
   123         HandleMark hm(thread);
   124         Universe::heap()->collect(GCCause::_scavenge_alot);
   125         unsigned int invocations = Universe::heap()->total_collections() - Universe::heap()->total_full_collections();
   126         // Compute new interval
   127         if (ScavengeALotInterval > 1) {
   128           _scavenge_alot_counter = 1+(long)((double)ScavengeALotInterval*os::random()/(max_jint+1.0));
   129           if (PrintGCDetails && Verbose) {
   130             tty->print_cr("Scavenge no: %u\tInterval: %d", invocations,
   131                           _scavenge_alot_counter);
   132           }
   133         } else {
   134           _scavenge_alot_counter = 1;
   135         }
   136         // Print progress message
   137         if (invocations % 1000 == 0) {
   138           if (PrintGCDetails && Verbose) tty->print_cr("Scavenge no: %u", invocations);
   139         }
   140       }
   141     }
   142   }
   143 }
   146 vframe* vframe_array[50];
   147 int walk_stack_counter = 0;
   149 void InterfaceSupport::walk_stack_from(vframe* start_vf) {
   150   // walk
   151   int i = 0;
   152   for (vframe* f = start_vf; f; f = f->sender() ) {
   153     if (i < 50) vframe_array[i++] = f;
   154   }
   155 }
   158 void InterfaceSupport::walk_stack() {
   159   JavaThread* thread = JavaThread::current();
   160   walk_stack_counter++;
   161   if (!thread->has_last_Java_frame()) return;
   162   ResourceMark rm(thread);
   163   RegisterMap reg_map(thread);
   164   walk_stack_from(thread->last_java_vframe(&reg_map));
   165 }
   168 # ifdef ENABLE_ZAP_DEAD_LOCALS
   170 static int zap_traversals = 0;
   172 void InterfaceSupport::zap_dead_locals_old() {
   173   JavaThread* thread = JavaThread::current();
   174   if (zap_traversals == -1) // edit constant for debugging
   175     warning("I am here");
   176   int zap_frame_count = 0; // count frames to help debugging
   177   for (StackFrameStream sfs(thread); !sfs.is_done(); sfs.next()) {
   178     sfs.current()->zap_dead_locals(thread, sfs.register_map());
   179     ++zap_frame_count;
   180   }
   181   ++zap_traversals;
   182 }
   184 # endif
   187 int deoptimizeAllCounter = 0;
   188 int zombieAllCounter = 0;
   191 void InterfaceSupport::zombieAll() {
   192   if (is_init_completed() && zombieAllCounter > ZombieALotInterval) {
   193     zombieAllCounter = 0;
   194     VM_ZombieAll op;
   195     VMThread::execute(&op);
   196   } else {
   197     zombieAllCounter++;
   198   }
   199 }
   201 void InterfaceSupport::deoptimizeAll() {
   202   if (is_init_completed() ) {
   203     if (DeoptimizeALot && deoptimizeAllCounter > DeoptimizeALotInterval) {
   204       deoptimizeAllCounter = 0;
   205       VM_DeoptimizeAll op;
   206       VMThread::execute(&op);
   207     } else if (DeoptimizeRandom && (deoptimizeAllCounter & 0x1f) == (os::random() & 0x1f)) {
   208       VM_DeoptimizeAll op;
   209       VMThread::execute(&op);
   210     }
   211   }
   212   deoptimizeAllCounter++;
   213 }
   216 void InterfaceSupport::stress_derived_pointers() {
   217 #ifdef COMPILER2
   218   JavaThread *thread = JavaThread::current();
   219   if (!is_init_completed()) return;
   220   ResourceMark rm(thread);
   221   bool found = false;
   222   for (StackFrameStream sfs(thread); !sfs.is_done() && !found; sfs.next()) {
   223     CodeBlob* cb = sfs.current()->cb();
   224     if (cb != NULL && cb->oop_maps() ) {
   225       // Find oopmap for current method
   226       OopMap* map = cb->oop_map_for_return_address(sfs.current()->pc());
   227       assert(map != NULL, "no oopmap found for pc");
   228       found = map->has_derived_pointer();
   229     }
   230   }
   231   if (found) {
   232     // $$$ Not sure what to do here.
   233     /*
   234     Scavenge::invoke(0);
   235     */
   236   }
   237 #endif
   238 }
   241 void InterfaceSupport::verify_stack() {
   242   JavaThread* thread = JavaThread::current();
   243   ResourceMark rm(thread);
   244   // disabled because it throws warnings that oop maps should only be accessed
   245   // in VM thread or during debugging
   247   if (!thread->has_pending_exception()) {
   248     // verification does not work if there are pending exceptions
   249     StackFrameStream sfs(thread);
   250     CodeBlob* cb = sfs.current()->cb();
   251       // In case of exceptions we might not have a runtime_stub on
   252       // top of stack, hence, all callee-saved registers are not going
   253       // to be setup correctly, hence, we cannot do stack verify
   254     if (cb != NULL && !(cb->is_runtime_stub() || cb->is_uncommon_trap_stub())) return;
   256     for (; !sfs.is_done(); sfs.next()) {
   257       sfs.current()->verify(sfs.register_map());
   258     }
   259   }
   260 }
   263 void InterfaceSupport::verify_last_frame() {
   264   JavaThread* thread = JavaThread::current();
   265   ResourceMark rm(thread);
   266   RegisterMap reg_map(thread);
   267   frame fr = thread->last_frame();
   268   fr.verify(&reg_map);
   269 }
   272 #endif // ASSERT
   275 void InterfaceSupport_init() {
   276 #ifdef ASSERT
   277   if (ScavengeALot || FullGCALot) {
   278     srand(ScavengeALotInterval * FullGCALotInterval);
   279   }
   280 #endif
   281 }

mercurial