Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java
64507 views
/*1* Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @key stress randomness26*27* @summary converted from VM Testbase gc/gctests/PhantomReference/phantom001.28* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent]29* VM Testbase readme:30* DESCRIPTION31* The test checks that Garbage Collector correctly works with32* PhantomReferences. It also checks that no unexpected exceptions and errors33* are thrown or the JVM is not crashed.34* The test starts a number of threads. Each thread run tests for some time35* or serveral iterations. See javadoc StressOptions for configuration.36* First of all each thread defines what type to check (there are 11 types37* totally). As soon as the type is defined, a PhantomRefence is created that38* refers to an array of tested type and is registered with in a queue. A39* PhantomRefence for NonbranchyTree and Referent calsses does not refer to40* arrays, but to instances of the classes.41* After that a thread performs next checks for the reference:42* 1. The reference is in queue after GC is provoked with43* Algorithms.eatMemory() method (a single thread eats the memory).44* 2. reference.get() returns null.45* 3. queue.poll() returns the reference that was created.46* 4. queue.poll() again returns null.47* 5. If the checked type is class (Referent), then it must be finalized,48* since the reference is already enqueued.49* 6. reference.clear() does not throw any exception.50* The test extends ThreadedGCTest and implements GarbageProducerAware and51* MemoryStrategyAware interfaces. The corresponding javadoc documentation52* for additional test configuration.53*54* @library /vmTestbase55* /test/lib56* @run main/othervm gc.gctests.PhantomReference.phantom001.phantom001 -ms low57*/5859package gc.gctests.PhantomReference.phantom001;6061import java.lang.ref.*;62import java.time.LocalTime;63import nsk.share.gc.*;64import nsk.share.gc.gp.*;65import nsk.share.gc.gp.string.InternedStringProducer;66import nsk.share.gc.gp.string.RandomStringProducer;6768public class phantom001 extends ThreadedGCTest implements GarbageProducerAware, MemoryStrategyAware {6970private GarbageProducer garbageProducer;71private MemoryStrategy memoryStrategy;72private InternedStringProducer internedStringProducer = new InternedStringProducer(new RandomStringProducer(10));73// Total number of types to test74final static int TYPES_COUNT = 12;75// Size of array of each tested type. The constant also specifies the76// number of nodes in a NonbranchyTree and size of each node77final static int SIZE = 100;7879protected Runnable createRunnable(int i) {80return new Test();81}8283public void setGarbageProducer(GarbageProducer garbageProducer) {84this.garbageProducer = garbageProducer;85}8687public void setMemoryStrategy(MemoryStrategy memoryStrategy) {88this.memoryStrategy = memoryStrategy;89}9091public static void main(String[] args) {92GC.runTest(new phantom001(), args);93}9495// The class implements the logic of the testcase96class Test implements Runnable, OOMStress {9798int iteration;99private volatile boolean finalized;100101private String addMessageContext(String message) {102return "T:" + Thread.currentThread().getId() +103" I:" + iteration +104" " + LocalTime.now().toString() +105": " + message;106}107108private void info(String message) {109log.info(addMessageContext(message));110}111112private void progress(String message) {113// Uncomment this to get more verbose logging.114// log.debug(addMessageContext(message));115}116117private void fail(String message) {118log.error(addMessageContext("[FAILED] " + message));119setFailed(true);120}121122private boolean shouldTerminate() {123return !getExecutionController().continueExecution();124}125126private void eatMemory(int initialFactor) {127GarbageUtils.eatMemory(getExecutionController(),128garbageProducer,129initialFactor, 10, 0);130}131132public void run() {133try {134int code = iteration % TYPES_COUNT;135info("start code " + code);136ReferenceQueue queue = new ReferenceQueue();137PhantomReference reference;138String type;139// Define a specific type for each thread to test140switch (code) {141case 0:142reference = new PhantomReference(new byte[SIZE], queue);143type = "byte";144break;145case 1:146reference = new PhantomReference(new short[SIZE], queue);147type = "short";148break;149case 2:150reference = new PhantomReference(new int[SIZE], queue);151type = "int";152break;153case 3:154reference = new PhantomReference(new long[SIZE], queue);155type = "long";156break;157case 4:158reference = new PhantomReference(new char[SIZE], queue);159type = "char";160break;161case 5:162reference = new PhantomReference(new boolean[SIZE], queue);163type = "boolean";164break;165case 6:166reference = new PhantomReference(new double[SIZE], queue);167type = "double";168break;169case 7:170reference = new PhantomReference(new float[SIZE], queue);171type = "float";172break;173case 8:174reference = new PhantomReference(new Object[SIZE], queue);175type = "Object";176break;177case 9:178reference = new PhantomReference(new NonbranchyTree(SIZE, 0.3f, SIZE),179queue);180type = "NonbranchyTree";181break;182case 10:183reference = new PhantomReference(internedStringProducer.create(SIZE), queue);184type = "InternedString";185break;186default:187reference = new PhantomReference(new Referent(), queue);188type = "class";189}190191int initialFactor = memoryStrategy.equals(MemoryStrategy.HIGH) ? 1 : (memoryStrategy.equals(MemoryStrategy.LOW) ? 10 : 2);192193// If referent is finalizable, provoke GCs and wait for finalization.194if (type.equals("class")) {195progress("Waiting for finalization: " + type);196for (int checks = 0; !finalized && !shouldTerminate(); ++checks) {197// There are scenarios where one eatMemory() isn't enough,198// but 10 iterations really ought to be sufficient.199if (checks > 10) {200fail("Waiting for finalization: " + type);201return;202}203eatMemory(initialFactor);204// Give some time for finalizer to run.205try {206Thread.sleep(100);207} catch (InterruptedException e) {}208}209}210211// Provoke GCs and wait for reference to be enqueued.212progress("Waiting for enqueue: " + type);213Reference polled = queue.poll();214for (int checks = 0; polled == null && !shouldTerminate(); ++checks) {215// There are scenarios where one eatMemory() isn't enough,216// but 10 iterations really ought to be sufficient.217if (checks > 10) {218fail("Waiting for enqueue: " + type);219return;220}221eatMemory(initialFactor);222// Give some time for reference to be enqueued.223try {224polled = queue.remove(100);225} catch (InterruptedException e) {}226}227228if (polled == null && shouldTerminate()) {229info("Terminated: " + type);230return;231}232233// The polled reference must be equal to the one enqueued to234// the queue235if (polled != reference) {236fail("The original reference is not equal to polled reference.");237return;238}239240// queue.poll() once again must return null now, since there is241// only one reference in the queue242if (queue.poll() != null) {243fail("There are more than one reference in the queue.");244return;245}246progress("Finished: " + type);247} catch (OutOfMemoryError e) {248} finally {249iteration++;250}251}252253class Referent {254255//We need discard this flag to make second and following checks with type.equals("class") useful256public Referent() {257finalized = false;258}259260protected void finalize() {261finalized = true;262}263}264}265266}267268269