1 /*
   2  * Copyright (c) 2002, 2018, 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  * @key stress gc
  27  *
  28  * @summary converted from VM Testbase gc/gctests/FinalizeTest01.
  29  * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, monitoring]
  30  *
  31  * @library /vmTestbase
  32  *          /test/lib
  33  * @run driver jdk.test.lib.FileInstaller . .
  34  * @run main/othervm -XX:-UseGCOverheadLimit gc.gctests.FinalizeTest01.FinalizeTest01
  35  */
  36 
  37 package gc.gctests.FinalizeTest01;
  38 
  39 import java.lang.management.ManagementFactory;
  40 import java.lang.management.MemoryMXBean;
  41 import nsk.share.gc.*;
  42 import nsk.share.TestFailure;
  43 import nsk.share.test.ExecutionController;
  44 import nsk.share.test.Stresser;
  45 
  46 /**
  47  * Tests that GC works correctly with finalizers.
  48  *
  49  * Create a number of objects, some of which register their
  50  * creation/finalization. Then try to eat available memory
  51  * which forces garbage collection of created objects.
  52  * Garbage collector should try to collect the garbage and thus
  53  * call finalizers. The test checks that all finalizers have been called.
  54  */
  55 
  56 /*
  57 Reworked original test (4933478). Original comment:
  58 
  59 Tests that objects w/finalizers will eventually finalize
  60 (and by the way, the system doesn't crash!).
  61 
  62 Returns exit code 0 on success, and 1 on failure.
  63 
  64  */
  65 /**
  66  * Class with finalizer that throws Exception.
  67  * Used for FinalizeTest02
  68  */
  69 class FinExceptMemoryObject extends FinMemoryObject {
  70 
  71     public FinExceptMemoryObject(int size) {
  72         super(size);
  73     }
  74 
  75     protected void finalize() {
  76         super.finalize();
  77         throw new RuntimeException("Exception in finalizer");
  78     }
  79 }
  80 
  81 public class FinalizeTest01 extends GCTestBase {
  82 
  83     private final int allocRatio = 5;
  84     private final int size = 1024 * 2;
  85     private int count = 1000;
  86     private static boolean throwExceptions = false;
  87     private ExecutionController stresser;
  88 
  89     private void runOne() {
  90         Object o;
  91         for (int i = 0; i < count; i++) {
  92             if (i % allocRatio == 0) {
  93                 if (throwExceptions) {
  94                     o = new FinExceptMemoryObject(size);
  95                 } else {
  96                     o = new FinMemoryObject(size);
  97                 }
  98             } else {
  99                 o = new byte[size - Memory.getObjectExtraSize()];
 100             }
 101         }
 102         o = null;
 103 
 104         MemoryMXBean mbean = ManagementFactory.getMemoryMXBean();
 105         long finalizationMaxTime = 1000 * 60; // 1min
 106 
 107         /* Provoke GC to start finalization. */
 108         Algorithms.eatMemory(stresser);
 109         if (!stresser.continueExecution()) {
 110             // we did not eat all memory
 111             return;
 112         }
 113         long waitTime = System.currentTimeMillis() + finalizationMaxTime;
 114 
 115         /*
 116          * Before we force finalization it is needed to check that we have
 117          * any object pending for finazlization. If not then is a GC bug.
 118          */
 119         while (FinMemoryObject.getFinalizedCount()
 120                 + mbean.getObjectPendingFinalizationCount() == 0
 121                 && (System.currentTimeMillis() < waitTime)) {
 122             System.out.println("No objects are found in the finalization queue. Waiting..");
 123             try {
 124                 Thread.sleep(1000);
 125             } catch (InterruptedException ie) {
 126             }
 127         }
 128         if (FinMemoryObject.getFinalizedCount()
 129                 + mbean.getObjectPendingFinalizationCount() == 0) {
 130             throw new TestFailure("Test failed. (No objects were not queued for finalization during 1min)");
 131         }
 132 
 133         /* force finalization and wait for it finishs */
 134         Runtime.getRuntime().runFinalization();
 135 
 136         boolean error = (FinMemoryObject.getLiveCount() != 0);
 137 
 138         /*
 139          * The runFinalization() starts the second finalization thread and wait until it finishs.
 140          * However it is a very little probability (less then 1%) that not all object are finalized yet.
 141          * Possibly the regular Finalizer thread have not finished its work when we check getLiveCount()
 142          * or GC is still clearing memory and adding objects to the queue.
 143          */
 144         waitTime = System.currentTimeMillis() + finalizationMaxTime;
 145         while (error && (System.currentTimeMillis() < waitTime)) {
 146             // wait 1 sec (it could be less due to potential InterruptedException)
 147             try {
 148                 Thread.sleep(1000);
 149             } catch (InterruptedException ie) {
 150             }
 151             error = (FinMemoryObject.getLiveCount() != 0);
 152         }
 153 
 154         if (error) {
 155             throw new TestFailure("Test failed (objects were not finalized during 1min)");
 156         }
 157 
 158 
 159         System.out.println("Allocated: " + FinMemoryObject.getAllocatedCount());
 160         System.out.println("Finalized: " + FinMemoryObject.getFinalizedCount());
 161         error = (FinMemoryObject.getLiveCount() != 0);
 162         if (error) {
 163             throw new TestFailure("Test failed.");
 164         }
 165     }
 166 
 167     public void run() {
 168         stresser = new Stresser(runParams.getStressOptions());
 169         stresser.start(runParams.getIterations());
 170         count = (int) Math.min(runParams.getTestMemory() / size, Integer.MAX_VALUE);
 171         System.out.println("Allocating " + count
 172                 + " objects. 1 out of " + allocRatio
 173                 + " will have a finalizer.");
 174         System.out.flush();
 175         runOne();
 176     }
 177 
 178     public static void main(String[] args) {
 179         for (int i = 0; i < args.length; ++i) {
 180             if (args[i].equals("-throwExceptions")) {
 181                 throwExceptions = true;
 182             }
 183         }
 184         GC.runTest(new FinalizeTest01(), args);
 185     }
 186 }