1 /* 2 * Copyright (c) 2011, 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 randomness 27 * 28 * @summary converted from VM Testbase gc/gctests/StringInternSyncWithGC. 29 * VM Testbase keywords: [gc, stress, stressopt, feature_perm_removal_jdk7, nonconcurrent] 30 * VM Testbase readme: 31 * The test verifies that String.intern is correctly synchronized with GC. 32 * Test interns and drop the same strings in different threads and provokes GC. 33 * Additionally test creates weak/soft references to interned strings. 34 * Test fails if any string object is inaccessible. 35 * 36 * @library /vmTestbase 37 * /test/lib 38 * @run driver jdk.test.lib.FileInstaller . . 39 * @run main/othervm 40 * -Xlog:gc:gc.log 41 * gc.gctests.StringInternSyncWithGC.StringInternSyncWithGC 42 * -ms low 43 * -memUsage 3 44 * -appTimeout 30 45 * -capacityVerPart 2 46 */ 47 48 package gc.gctests.StringInternSyncWithGC; 49 50 import java.util.ArrayList; 51 import java.util.List; 52 53 import nsk.share.gc.*; 54 import nsk.share.gc.gp.MemoryStrategy; 55 import nsk.share.gc.gp.MemoryStrategyAware; 56 import nsk.share.gc.gp.string.RandomStringProducer; 57 import nsk.share.test.ExecutionController; 58 59 public class StringInternSyncWithGC extends ThreadedGCTest implements MemoryStrategyAware { 60 61 // Maximum size of one string 62 // Depends from all size and memory strategy 63 private int maxStringSize; 64 private MemoryStrategy memoryStrategy; 65 private final int memUsageFactor; 66 private final long endTimeCapacityVer; 67 68 // The list of strings which are interned during iteration 69 private final List<String> stringsToIntern = new ArrayList(); 70 private final RandomStringProducer gp = new RandomStringProducer(); 71 72 public StringInternSyncWithGC(int memUsage, long endTimeCapVer) { 73 memUsageFactor = memUsage; 74 endTimeCapacityVer = endTimeCapVer; 75 } 76 77 @Override 78 public void setMemoryStrategy(MemoryStrategy memoryStrategy) { 79 this.memoryStrategy = memoryStrategy; 80 } 81 82 /** 83 * Verify that we could use certain amount of memory. 84 */ 85 private boolean verifyInternedStringCapacity(long initialSize) { 86 long currentSize = 0; 87 final int STEP = 1000; 88 int iter = 0; 89 char[] template = new char[(int) (initialSize / STEP)]; 90 91 List<String> tmpList = new ArrayList<>(STEP); 92 try { 93 while (currentSize <= initialSize) { 94 if (endTimeCapacityVer < System.currentTimeMillis()) { 95 log.debug("Too long to verify interned string capacity"); 96 log.debug("Silently pass."); 97 return false; 98 } 99 template[iter]++; 100 if (++iter == template.length) { 101 iter = 0; 102 } 103 String str = new String(template); 104 tmpList.add(str.intern()); 105 currentSize += str.length() * 2; //each char costs 2 bytes 106 } 107 } catch (OutOfMemoryError oome) { 108 log.debug("It is not possible to allocate " + initialSize + " size of interned string."); 109 log.debug("Silently pass."); 110 return false; 111 } 112 return true; 113 } 114 115 @Override 116 public void run() { 117 long size = runParams.getTestMemory() / memUsageFactor; 118 if (!verifyInternedStringCapacity(size)) { 119 return; 120 } 121 // Approximate size occupied by all interned strings 122 long sizeOfAllInternedStrings = size / 2; 123 maxStringSize = (int) (sizeOfAllInternedStrings / memoryStrategy.getSize(sizeOfAllInternedStrings, Memory.getObjectExtraSize())); 124 // Each thread keeps reference to each created string. 125 long extraConsumption = runParams.getNumberOfThreads() * Memory.getReferenceSize(); 126 log.debug("The overall size of interned strings : " + sizeOfAllInternedStrings / (1024 * 1024) + "M"); 127 log.debug("The count of interned strings : " + sizeOfAllInternedStrings / (maxStringSize + extraConsumption)); 128 for (long currentSize = 0; currentSize <= sizeOfAllInternedStrings; 129 currentSize += maxStringSize + extraConsumption) { 130 stringsToIntern.add(gp.create(maxStringSize)); 131 } 132 super.run(); 133 } 134 135 @Override 136 protected Runnable createRunnable(int threadId) { 137 return new StringGenerator(threadId, this); 138 } 139 140 public static void main(String[] args) { 141 int appTimeout = -1; 142 int memUsageFactor = 1; 143 // Part of time that function verifyInternedStringCapacity can take. Time = Application_Timeout / capacityVerTimePart 144 double capacityVerPart = 2; 145 for (int i = 0; i < args.length; ++i) { 146 switch (args[i]) { 147 case "-memUsage": 148 memUsageFactor = Integer.parseInt(args[i + 1]); 149 break; 150 case "-capacityVerPart": 151 capacityVerPart = Double.parseDouble(args[i + 1]); 152 break; 153 case "-appTimeout": 154 appTimeout = Integer.parseInt(args[i + 1]); 155 break; 156 default: 157 } 158 } 159 if (appTimeout == -1) { 160 throw new IllegalArgumentException("Specify -appTimeout."); 161 } 162 long endTimeCapacityVer = System.currentTimeMillis() + (long) (appTimeout / capacityVerPart * 60000); 163 GC.runTest(new StringInternSyncWithGC(memUsageFactor, endTimeCapacityVer), args); 164 } 165 166 protected List<String> getStringsToIntern() { 167 return stringsToIntern; 168 } 169 170 protected int getNumberOfThreads() { 171 return runParams.getNumberOfThreads(); 172 } 173 174 protected RandomStringProducer getGarbageProducer() { 175 return gp; 176 } 177 178 protected int getMaxStringSize() { 179 return maxStringSize; 180 } 181 182 protected ExecutionController getExecController() { 183 return getExecutionController(); 184 } 185 }