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 package nsk.monitoring.ThreadMXBean; 25 26 import java.util.ArrayList; 27 import java.util.List; 28 import nsk.share.gc.gp.GarbageProducer; 29 import nsk.share.gc.gp.GarbageUtils; 30 import nsk.share.test.Stresser; 31 32 33 public class MXBeanTestThread extends Thread { 34 35 /** 36 * BarrierHandler instance for synchronization with management thread 37 */ 38 protected BarrierHandler handler; 39 40 /** 41 * List where allocated objects are stored 42 */ 43 private List<Object> allocatedList; 44 /** 45 * Number of simultaneously running threads 46 */ 47 private static int threadCount; 48 /** 49 * java.util.Random instance for stress test (allocateStress()) 50 */ 51 private java.util.Random random = new java.util.Random(); 52 /** 53 * Expected amount of memory allocated during stress test 54 */ 55 private long stressAllocatedBytes; 56 /** 57 * Maximum memory in bytes that one thread is allowed to use at once 58 */ 59 private long maxThreadMemory = 0; 60 /** 61 * GarbageProducer for objects creation 62 */ 63 private GarbageProducer gp; 64 /** 65 * Stresser instance for allocateStress() 66 */ 67 private Stresser stresser; 68 warmUp(String garbageProducerId)69 public static void warmUp(String garbageProducerId) { 70 MXBeanTestThread warmUpThread = new MXBeanTestThread(garbageProducerId) { 71 @Override 72 public void doWork() { 73 allocate(); 74 } 75 }; 76 warmUpThread.start(); 77 do { 78 try { 79 warmUpThread.join(); 80 } catch (InterruptedException ie) {} 81 } while(warmUpThread.isAlive()); 82 } 83 84 /** 85 * Sets BarrierHandler for this thread 86 * 87 * @param handler BarrierHandler to synchronize with 88 */ setHandler(BarrierHandler handler)89 public void setHandler(BarrierHandler handler) { 90 this.handler = handler; 91 } 92 93 /** 94 * Returns an instance of MXBeanTestThread with already defined 95 * allocatedList List and GarbageProducer 96 */ MXBeanTestThread(String garbageProducerId)97 public MXBeanTestThread(String garbageProducerId) { 98 super(Integer.toString(++threadCount)); 99 allocatedList = new ArrayList<Object>(); 100 gp = GarbageUtils.getGarbageProducer(garbageProducerId); 101 maxThreadMemory = Runtime.getRuntime().maxMemory()/4; 102 } 103 104 /** 105 * Returns an instance of MXBeanTestThread with already defined 106 * allocatedList List and default GarbageProducer 107 */ MXBeanTestThread()108 public MXBeanTestThread() { 109 this("intArr"); 110 } 111 112 /** 113 * Returns an instance of MXBeanTestThread with already defined 114 * allocatedList List and Stresser 115 */ MXBeanTestThread(Stresser stresser)116 public MXBeanTestThread(Stresser stresser) { 117 this("intArr"); 118 this.stresser = stresser; 119 } 120 121 /** 122 * Sets maximum amount of memory that could be used at once for each 123 * TestThread in StressTest 124 */ setMaxThreadMemory(long memory)125 public void setMaxThreadMemory (long memory) { 126 maxThreadMemory = memory; 127 } 128 129 /** 130 * Returns expected memory allocated by TestThread during StressTest 131 * @return expected memory amount 132 */ getStressAllocatedBytes()133 public long getStressAllocatedBytes() { 134 return stressAllocatedBytes; 135 } 136 137 @Override run()138 public void run() { 139 doWork(); 140 } 141 142 /** 143 * Implementation of TestThread behavior logic 144 */ doWork()145 public void doWork() { 146 handler.ready(); 147 allocate(); 148 handler.ready(); 149 } 150 151 /** 152 * Allocates memory for amount of time specified in Stresser instance 153 */ allocateStress()154 protected void allocateStress() { 155 // Size of long[] array that allocates 2 Mb + 1 byte 156 int MAX_ARR_SIZE=262146; 157 // Anount of memory allocated by thread with existing links 158 // Which means that these objects can't be collected by GC 159 long actuallyAllocated = 0; 160 try { 161 while (stresser.continueExecution()) { 162 //int chunkSize = random.nextInt(MAX_OBJECT_SIZE); 163 //Object obj = gp.create(chunkSize); 164 int chunkSize = random.nextInt(MAX_ARR_SIZE); 165 Object obj = new long[chunkSize]; 166 allocatedList.add(obj); 167 actuallyAllocated += chunkSize*8; 168 if (actuallyAllocated > maxThreadMemory) { 169 // Allocated more then allowed to one thread 170 // re-define allocatedList to allow GC to delete 171 // created objects 172 stressAllocatedBytes += actuallyAllocated; 173 actuallyAllocated = 0; 174 allocatedList = new ArrayList<Object>(); 175 } 176 } 177 } catch (OutOfMemoryError e) { 178 } finally { 179 stressAllocatedBytes += actuallyAllocated; 180 } 181 } 182 183 /** 184 * Allocates memory once according test settings 185 */ allocate()186 protected void allocate() { 187 long actuallyAllocated = 0; 188 for (int i = 0; i < ThreadMXBeanTestBase.allocArr.length; i++) { 189 long size = ThreadMXBeanTestBase.allocArr[i]; 190 if (actuallyAllocated + size > maxThreadMemory) { 191 break; 192 } 193 allocatedList.add(gp.create(size)); 194 actuallyAllocated += size; 195 } 196 } 197 } 198