/* * 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. */ package gc.hashcode; import java.util.ArrayList; import java.util.Random; /** * Helper class for the hash code tests. */ public final class HCHelper { /** * Evacuation list 0 constant. */ public static final int EVAC_LIST_0 = 0; /** * Evacuation list 1 constant. */ public static final int EVAC_LIST_1 = 1; /** * Evacuation list 2 constant. */ public static final int EVAC_LIST_2 = 2; /** * Evacuation list 3 constant. */ public static final int EVAC_LIST_3 = 3; /** * Evacuation list 4 constant. */ public static final int EVAC_LIST_4 = 4; /** * Evacuation list 5 constant. */ public static final int EVAC_LIST_5 = 5; /** * Evacuation list 0 percentage constant. */ public static final double EVAC_SIZE_0 = 0.50; /** * Evacuation list 1 percentage constant. */ public static final double EVAC_SIZE_1 = 0.14; /** * Evacuation list 2 percentage constant. */ public static final double EVAC_SIZE_2 = 0.12; /** * Evacuation list 3 percentage constant. */ public static final double EVAC_SIZE_3 = 0.10; /** * Evacuation list 4 percentage constant. */ public static final double EVAC_SIZE_4 = 0.07; /** * Evacuation list 5 percentage constant. */ public static final double EVAC_SIZE_5 = 0.05; /** * Helper class that allocates memory and also tracks the original * as well as current hash code. */ final class AllocObject { private byte[] allocatedArray; private int hashValue; /** * Create a new allocator object that allocates size bytes. * * @param size Number of bytes to allocate. */ AllocObject(int size) { allocatedArray = new byte[size]; hashValue = allocatedArray.hashCode(); } /** * Get the stored hash code value. * * @return Stored hash code. */ int getStoredHashValue() { return hashValue; } /** * Get the current hash code value. * * @return Current hash code. */ int getCurrentHashValue() { return allocatedArray.hashCode(); } /** * Get the size of the allocated object. * * @return Size of allocated object. */ int getAllocatedSize() { return allocatedArray.length; } } /** * Helper class that holds all the allocation lists. */ final class AllocInfo { private long allocatedSize; private long numOfAllocedObjs; private ArrayList safeList; private ArrayList allocList; private ArrayList evacList0; private ArrayList evacList1; private ArrayList evacList2; private ArrayList evacList3; private ArrayList evacList4; private ArrayList evacList5; /** * Create the helper object. */ AllocInfo() { allocatedSize = 0; numOfAllocedObjs = 0; safeList = new ArrayList(); allocList = new ArrayList(); evacList0 = new ArrayList(); evacList1 = new ArrayList(); evacList2 = new ArrayList(); evacList3 = new ArrayList(); evacList4 = new ArrayList(); evacList5 = new ArrayList(); } /** * Get the amount of memory allocated in total. * * @return Total allocated size. */ public long getAllocatedSize() { return allocatedSize; } /** * Set the amount of memory allocated in total. * * @param allocatedSize Total allocated size. */ public void setAllocatedSize(long allocatedSize) { this.allocatedSize = allocatedSize; } /** * Get total number of objects allocated. * * @return Number of objects allocated. */ public long getNumOfAllocedObjs() { return numOfAllocedObjs; } /** * Set total number of objects allocated. * * @param numOfAllocedObjs Number of objects allocated. */ public void setNumOfAllocedObjs(long numOfAllocedObjs) { this.numOfAllocedObjs = numOfAllocedObjs; } /** * Increase the number of objects allocated. */ public void incNumOfAllocedObjs() { numOfAllocedObjs++; } /** * Decrease the number of objects allocated. */ public void decNumOfAllocedObjs() { numOfAllocedObjs--; } /** * Get the safe list. * * @return ArrayList that contains the safe list. */ public ArrayList getSafeList() { return safeList; } /** * Get the alloc list. * * @return ArrayList that contains the alloc list. */ public ArrayList getAllocList() { return allocList; } /** * Get evacuation list 0. * * @return ArrayList that contains evacuation list 0. */ public ArrayList getEvacList0() { return evacList0; } /** * Get evacuation list 1. * * @return ArrayList that contains evacuation list 1. */ public ArrayList getEvacList1() { return evacList1; } /** * Get evacuation list 2. * * @return ArrayList that contains evacuation list 2. */ public ArrayList getEvacList2() { return evacList2; } /** * Get evacuation list 3. * * @return ArrayList that contains evacuation list 3. */ public ArrayList getEvacList3() { return evacList3; } /** * Get evacuation list 4. * * @return ArrayList that contains evacuation list 4. */ public ArrayList getEvacList4() { return evacList4; } /** * Get evacuation list 5. * * @return ArrayList that contains evacuation list 5. */ public ArrayList getEvacList5() { return evacList5; } } private int minSize; private int maxSize; private double percentToFill; private int allocTrigSize; private AllocInfo ai; private Random rnd; private long sizeLimit0; private long sizeLimit1; private long sizeLimit2; private long sizeLimit3; private long sizeLimit4; private long sizeLimit5; /** * Create the helper class. * * @param minSize Minimum size of objects to allocate. * @param maxSize Maximum size of objects to allocate. * @param seed Random seed to use. * @param percentToFill Percentage of the heap to fill. * @param allocTrigSize Object size to use when triggering a GC. */ public HCHelper(int minSize, int maxSize, long seed, double percentToFill, int allocTrigSize) { this.minSize = minSize; this.maxSize = maxSize; this.percentToFill = percentToFill; this.allocTrigSize = allocTrigSize; ai = new AllocInfo(); rnd = new Random(seed); sizeLimit0 = 0; sizeLimit1 = 0; sizeLimit2 = 0; sizeLimit3 = 0; sizeLimit4 = 0; sizeLimit5 = 0; } /** * Setup all the evacuation lists and fill them with objects. */ public void setupLists() { Runtime r = Runtime.getRuntime(); long maxMem = r.maxMemory(); long safeMaxMem = (long) (maxMem * percentToFill); sizeLimit0 = (long) (safeMaxMem * EVAC_SIZE_0); sizeLimit1 = (long) (safeMaxMem * EVAC_SIZE_1); sizeLimit2 = (long) (safeMaxMem * EVAC_SIZE_2); sizeLimit3 = (long) (safeMaxMem * EVAC_SIZE_3); sizeLimit4 = (long) (safeMaxMem * EVAC_SIZE_4); sizeLimit5 = (long) (safeMaxMem * EVAC_SIZE_5); // Fill the memory with objects System.gc(); allocObjects(ai.getEvacList0(), sizeLimit0); System.gc(); allocObjects(ai.getEvacList1(), sizeLimit1); System.gc(); allocObjects(ai.getEvacList2(), sizeLimit2); System.gc(); allocObjects(ai.getEvacList3(), sizeLimit3); System.gc(); allocObjects(ai.getEvacList4(), sizeLimit4); System.gc(); allocObjects(ai.getEvacList5(), sizeLimit5); System.gc(); } private void allocObjects(ArrayList al, long totalSizeLimit) { long allocedSize = 0; int multiplier = maxSize - minSize; while (allocedSize < totalSizeLimit) { int allocSize = minSize + (int) (rnd.nextDouble() * multiplier); if (allocSize >= totalSizeLimit - allocedSize) { allocSize = (int) (totalSizeLimit - allocedSize); } al.add(new AllocObject(allocSize)); allocedSize += allocSize; } } /** * Free all objects in a specific evacuation list. * * @param listNr The evacuation list to clear. Must be between 0 and 5. */ public void clearList(int listNr) { if (listNr < EVAC_LIST_0 || listNr > EVAC_LIST_5) { throw new IllegalArgumentException("List to removed bust be " + "between EVAC_LIST_0 and EVAC_LIST_5"); } switch (listNr) { case EVAC_LIST_0: ai.getEvacList0().clear(); break; case EVAC_LIST_1: ai.getEvacList1().clear(); break; case EVAC_LIST_2: ai.getEvacList2().clear(); break; case EVAC_LIST_3: ai.getEvacList3().clear(); break; case EVAC_LIST_4: ai.getEvacList4().clear(); break; case EVAC_LIST_5: ai.getEvacList5().clear(); break; default: // Should never occur, since we test the listNr param break; } } /** * Verify the hash codes for a list of AllocObject:s. * * @param objList ArrayList containing AllocObject:s * @return true if all hash codes are OK, otherwise false */ boolean verifyHashCodes(ArrayList objList) { // Check the hash values for (int i = 0; i < objList.size(); i++) { AllocObject tmp = (AllocObject) objList.get(i); if (tmp.getStoredHashValue() != tmp.getCurrentHashValue()) { // At least one of the hash values mismatch, so the test failed return false; } } return true; } /** * Verify the hash codes for all objects in all the lists. * * @return Success if all hash codes matches the original hash codes. */ public boolean verifyHashCodes() { return verifyHashCodes(ai.getAllocList()) && verifyHashCodes(ai.getSafeList()) && verifyHashCodes(ai.getEvacList0()) && verifyHashCodes(ai.getEvacList1()) && verifyHashCodes(ai.getEvacList2()) && verifyHashCodes(ai.getEvacList3()) && verifyHashCodes(ai.getEvacList4()) && verifyHashCodes(ai.getEvacList5()); } /** * Free all allocated objects from all the lists. */ public void cleanupLists() { ai.getAllocList().clear(); ai.getSafeList().clear(); ai.getEvacList0().clear(); ai.getEvacList1().clear(); ai.getEvacList2().clear(); ai.getEvacList3().clear(); ai.getEvacList4().clear(); ai.getEvacList5().clear(); } /** * Get the size of evacuation list 0. * * @return Size of evacuation list 0. */ public long getEvac0Size() { return sizeLimit0; } /** * Get the size of evacuation list 1. * * @return Size of evacuation list 1. */ public long getEvac1Size() { return sizeLimit1; } /** * Get the size of evacuation list 2. * * @return Size of evacuation list 2. */ public long getEvac2Size() { return sizeLimit2; } /** * Get the size of evacuation list 3. * * @return Size of evacuation list 3. */ public long getEvac3Size() { return sizeLimit3; } /** * Get the size of evacuation list 4. * * @return Size of evacuation list 4. */ public long getEvac4Size() { return sizeLimit4; } /** * Get the size of evacuation list 5. * * @return Size of evacuation list 5. */ public long getEvac5Size() { return sizeLimit5; } }