| /* |
| * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * @test |
| * @key stress gc |
| * |
| * @summary converted from VM Testbase gc/gctests/StringInternSyncWithGC. |
| * VM Testbase keywords: [gc, stress, stressopt, feature_perm_removal_jdk7, nonconcurrent] |
| * VM Testbase readme: |
| * The test verifies that String.intern is correctly synchronized with GC. |
| * Test interns and drop the same strings in different threads and provokes GC. |
| * Additionally test creates weak/soft references to interned strings. |
| * Test fails if any string object is inaccessible. |
| * |
| * @library /vmTestbase |
| * /test/lib |
| * @run driver jdk.test.lib.FileInstaller . . |
| * @run main/othervm |
| * -Xlog:gc:gc.log |
| * gc.gctests.StringInternSyncWithGC.StringInternSyncWithGC |
| * -ms low |
| * -memUsage 3 |
| * -appTimeout 30 |
| * -capacityVerPart 2 |
| */ |
| |
| package gc.gctests.StringInternSyncWithGC; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import nsk.share.gc.*; |
| import nsk.share.gc.gp.MemoryStrategy; |
| import nsk.share.gc.gp.MemoryStrategyAware; |
| import nsk.share.gc.gp.string.RandomStringProducer; |
| import nsk.share.test.ExecutionController; |
| |
| public class StringInternSyncWithGC extends ThreadedGCTest implements MemoryStrategyAware { |
| |
| // Maximum size of one string |
| // Depends from all size and memory strategy |
| private int maxStringSize; |
| private MemoryStrategy memoryStrategy; |
| private final int memUsageFactor; |
| private final long endTimeCapacityVer; |
| |
| // The list of strings which are interned during iteration |
| private final List<String> stringsToIntern = new ArrayList(); |
| private final RandomStringProducer gp = new RandomStringProducer(); |
| |
| public StringInternSyncWithGC(int memUsage, long endTimeCapVer) { |
| memUsageFactor = memUsage; |
| endTimeCapacityVer = endTimeCapVer; |
| } |
| |
| @Override |
| public void setMemoryStrategy(MemoryStrategy memoryStrategy) { |
| this.memoryStrategy = memoryStrategy; |
| } |
| |
| /** |
| * Verify that we could use certain amount of memory. |
| */ |
| private boolean verifyInternedStringCapacity(long initialSize) { |
| long currentSize = 0; |
| final int STEP = 1000; |
| int iter = 0; |
| char[] template = new char[(int) (initialSize / STEP)]; |
| |
| List<String> tmpList = new ArrayList<>(STEP); |
| try { |
| while (currentSize <= initialSize) { |
| if (endTimeCapacityVer < System.currentTimeMillis()) { |
| log.debug("Too long to verify interned string capacity"); |
| log.debug("Silently pass."); |
| return false; |
| } |
| template[iter]++; |
| if (++iter == template.length) { |
| iter = 0; |
| } |
| String str = new String(template); |
| tmpList.add(str.intern()); |
| currentSize += str.length() * 2; //each char costs 2 bytes |
| } |
| } catch (OutOfMemoryError oome) { |
| log.debug("It is not possible to allocate " + initialSize + " size of interned string."); |
| log.debug("Silently pass."); |
| return false; |
| } |
| return true; |
| } |
| |
| @Override |
| public void run() { |
| long size = runParams.getTestMemory() / memUsageFactor; |
| if (!verifyInternedStringCapacity(size)) { |
| return; |
| } |
| // Approximate size occupied by all interned strings |
| long sizeOfAllInternedStrings = size / 2; |
| maxStringSize = (int) (sizeOfAllInternedStrings / memoryStrategy.getSize(sizeOfAllInternedStrings, Memory.getObjectExtraSize())); |
| // Each thread keeps reference to each created string. |
| long extraConsumption = runParams.getNumberOfThreads() * Memory.getReferenceSize(); |
| log.debug("The overall size of interned strings : " + sizeOfAllInternedStrings / (1024 * 1024) + "M"); |
| log.debug("The count of interned strings : " + sizeOfAllInternedStrings / (maxStringSize + extraConsumption)); |
| for (long currentSize = 0; currentSize <= sizeOfAllInternedStrings; |
| currentSize += maxStringSize + extraConsumption) { |
| stringsToIntern.add(gp.create(maxStringSize)); |
| } |
| super.run(); |
| } |
| |
| @Override |
| protected Runnable createRunnable(int threadId) { |
| return new StringGenerator(threadId, this); |
| } |
| |
| public static void main(String[] args) { |
| int appTimeout = -1; |
| int memUsageFactor = 1; |
| // Part of time that function verifyInternedStringCapacity can take. Time = Application_Timeout / capacityVerTimePart |
| double capacityVerPart = 2; |
| for (int i = 0; i < args.length; ++i) { |
| switch (args[i]) { |
| case "-memUsage": |
| memUsageFactor = Integer.parseInt(args[i + 1]); |
| break; |
| case "-capacityVerPart": |
| capacityVerPart = Double.parseDouble(args[i + 1]); |
| break; |
| case "-appTimeout": |
| appTimeout = Integer.parseInt(args[i + 1]); |
| break; |
| default: |
| } |
| } |
| if (appTimeout == -1) { |
| throw new IllegalArgumentException("Specify -appTimeout."); |
| } |
| long endTimeCapacityVer = System.currentTimeMillis() + (long) (appTimeout / capacityVerPart * 60000); |
| GC.runTest(new StringInternSyncWithGC(memUsageFactor, endTimeCapacityVer), args); |
| } |
| |
| protected List<String> getStringsToIntern() { |
| return stringsToIntern; |
| } |
| |
| protected int getNumberOfThreads() { |
| return runParams.getNumberOfThreads(); |
| } |
| |
| protected RandomStringProducer getGarbageProducer() { |
| return gp; |
| } |
| |
| protected int getMaxStringSize() { |
| return maxStringSize; |
| } |
| |
| protected ExecutionController getExecController() { |
| return getExecutionController(); |
| } |
| } |