| /* |
| * 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; |
| } |
| } |