Path: blob/master/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/phantom001/phantom001.java
41161 views
/*1* Copyright (c) 2004, 2020, 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 nsk.share.gc.*;63import nsk.share.gc.gp.*;64import nsk.share.gc.gp.string.InternedStringProducer;65import nsk.share.gc.gp.string.RandomStringProducer;6667public class phantom001 extends ThreadedGCTest implements GarbageProducerAware, MemoryStrategyAware {6869private GarbageProducer garbageProducer;70private MemoryStrategy memoryStrategy;71private InternedStringProducer internedStringProducer = new InternedStringProducer(new RandomStringProducer(10));72// Total number of types to test73final static int TYPES_COUNT = 12;74// Size of array of each tested type. The constant also specifies the75// number of nodes in a NonbranchyTree and size of each node76final static int SIZE = 100;7778protected Runnable createRunnable(int i) {79return new Test();80}8182public void setGarbageProducer(GarbageProducer garbageProducer) {83this.garbageProducer = garbageProducer;84}8586public void setMemoryStrategy(MemoryStrategy memoryStrategy) {87this.memoryStrategy = memoryStrategy;88}8990public static void main(String[] args) {91GC.runTest(new phantom001(), args);92}9394// The class implements the logic of the testcase95class Test implements Runnable {9697int iteration;98private volatile boolean finalized;99100public void run() {101try {102log.info("iteration " + iteration);103ReferenceQueue queue = new ReferenceQueue();104PhantomReference reference;105int code = iteration % TYPES_COUNT;106String type;107// Define a specific type for each thread to test108switch (code) {109case 0:110reference = new PhantomReference(new byte[SIZE], queue);111type = "byte";112break;113case 1:114reference = new PhantomReference(new short[SIZE], queue);115type = "short";116break;117case 2:118reference = new PhantomReference(new int[SIZE], queue);119type = "int";120break;121case 3:122reference = new PhantomReference(new long[SIZE], queue);123type = "long";124break;125case 4:126reference = new PhantomReference(new char[SIZE], queue);127type = "char";128break;129case 5:130reference = new PhantomReference(new boolean[SIZE], queue);131type = "boolean";132break;133case 6:134reference = new PhantomReference(new double[SIZE], queue);135type = "double";136break;137case 7:138reference = new PhantomReference(new float[SIZE], queue);139type = "float";140break;141case 8:142reference = new PhantomReference(new Object[SIZE], queue);143type = "Object";144break;145case 9:146reference = new PhantomReference(new NonbranchyTree(SIZE, 0.3f, SIZE),147queue);148type = "NonbranchyTree";149break;150case 10:151reference = new PhantomReference(internedStringProducer.create(SIZE), queue);152type = "InternedString";153break;154default:155reference = new PhantomReference(new Referent(), queue);156type = "class";157}158159int initialFactor = memoryStrategy.equals(MemoryStrategy.HIGH) ? 1 : (memoryStrategy.equals(MemoryStrategy.LOW) ? 10 : 2);160GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0);161if (type.equals("class")) {162while (!finalized && getExecutionController().continueExecution()) {163System.runFinalization(); //does not guarantee finalization, but increases the chance164try {165Thread.sleep(100);166} catch (InterruptedException e) {}167GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0);168}169170//provoke gc once more to make finalized object phantom reachable171GarbageUtils.eatMemory(getExecutionController(), garbageProducer, initialFactor , 10, 0);172}173if (!getExecutionController().continueExecution()) {174// we were interrrupted by stresser. just exit...175return;176}177Reference polledReference = null;178try {179polledReference = queue.remove();180} catch (InterruptedException e) {181log.error("Unexpected InterruptedException during queue.remove().");182setFailed(true);183}184// Check the reference and the queue185// The polled reference must be equal to the one enqueued to186// the queue187188if (polledReference != reference) {189log.error("The original reference is not equal to polled reference.");190setFailed(true);191}192193// queue.poll() once again must return null now, since there is194// only one reference in the queue195polledReference = queue.poll();196if (polledReference != null) {197log.error("There are more than one references in the queue.");198setFailed(true);199}200reference.clear();201} catch (OutOfMemoryError e) {202}203iteration++;204}205206class Referent {207208//We need discard this flag to make second and following checks with type.equals("class") useful209public Referent() {210finalized = false;211}212213protected void finalize() {214finalized = true;215}216}217}218219}220221222