jdk/test/java/lang/ref/OOMEInReferenceHandler.java
changeset 17716 f9486b530c80
child 18792 dbac92e2a5e8
equal deleted inserted replaced
17715:9d2234cba0ff 17716:f9486b530c80
       
     1 /*
       
     2  * Copyright (c) 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 
       
    24 /**
       
    25  * @test
       
    26  * @bug 7038914
       
    27  * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
       
    28  * @run main/othervm -Xmx16M -XX:-UseTLAB OOMEInReferenceHandler
       
    29  * @author peter.levart@gmail.com
       
    30  */
       
    31 
       
    32 import java.lang.ref.*;
       
    33 
       
    34 public class OOMEInReferenceHandler {
       
    35      static Object[] fillHeap() {
       
    36          Object[] first = null, last = null;
       
    37          int size = 1 << 20;
       
    38          while (size > 0) {
       
    39              try {
       
    40                  Object[] array = new Object[size];
       
    41                  if (first == null) {
       
    42                      first = array;
       
    43                  } else {
       
    44                      last[0] = array;
       
    45                  }
       
    46                  last = array;
       
    47              } catch (OutOfMemoryError oome) {
       
    48                  size = size >>> 1;
       
    49              }
       
    50          }
       
    51          return first;
       
    52      }
       
    53 
       
    54      public static void main(String[] args) throws Exception {
       
    55          // preinitialize the InterruptedException class so that the reference handler
       
    56          // does not die due to OOME when loading the class if it is the first use
       
    57          InterruptedException ie = new InterruptedException("dummy");
       
    58 
       
    59          ThreadGroup tg = Thread.currentThread().getThreadGroup();
       
    60          for (
       
    61              ThreadGroup tgn = tg;
       
    62              tgn != null;
       
    63              tg = tgn, tgn = tg.getParent()
       
    64              )
       
    65              ;
       
    66 
       
    67          Thread[] threads = new Thread[tg.activeCount()];
       
    68          Thread referenceHandlerThread = null;
       
    69          int n = tg.enumerate(threads);
       
    70          for (int i = 0; i < n; i++) {
       
    71              if ("Reference Handler".equals(threads[i].getName())) {
       
    72                  referenceHandlerThread = threads[i];
       
    73              }
       
    74          }
       
    75 
       
    76          if (referenceHandlerThread == null) {
       
    77              throw new IllegalStateException("Couldn't find Reference Handler thread.");
       
    78          }
       
    79 
       
    80          ReferenceQueue<Object> refQueue = new ReferenceQueue<>();
       
    81          Object referent = new Object();
       
    82          WeakReference<Object> weakRef = new WeakReference<>(referent, refQueue);
       
    83 
       
    84          Object waste = fillHeap();
       
    85 
       
    86          referenceHandlerThread.interrupt();
       
    87 
       
    88          // allow referenceHandlerThread some time to throw OOME
       
    89          Thread.sleep(500L);
       
    90 
       
    91          // release waste & referent
       
    92          waste = null;
       
    93          referent = null;
       
    94 
       
    95          // wait at most 10 seconds for success or failure
       
    96          for (int i = 0; i < 20; i++) {
       
    97              if (refQueue.poll() != null) {
       
    98                  // Reference Handler thread still working -> success
       
    99                  return;
       
   100              }
       
   101              System.gc();
       
   102              Thread.sleep(500L); // wait a little to allow GC to do it's work before allocating objects
       
   103              if (!referenceHandlerThread.isAlive()) {
       
   104                  // Reference Handler thread died -> failure
       
   105                  throw new Exception("Reference Handler thread died.");
       
   106              }
       
   107          }
       
   108 
       
   109          // no sure answer after 10 seconds
       
   110          throw new IllegalStateException("Reference Handler thread stuck.");
       
   111      }
       
   112 }