| /* |
| * 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 nsk.monitoring.ThreadMXBean; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import nsk.share.gc.gp.GarbageProducer; |
| import nsk.share.gc.gp.GarbageUtils; |
| import nsk.share.test.Stresser; |
| |
| |
| public class MXBeanTestThread extends Thread { |
| |
| /** |
| * BarrierHandler instance for synchronization with management thread |
| */ |
| protected BarrierHandler handler; |
| |
| /** |
| * List where allocated objects are stored |
| */ |
| private List<Object> allocatedList; |
| /** |
| * Number of simultaneously running threads |
| */ |
| private static int threadCount; |
| /** |
| * java.util.Random instance for stress test (allocateStress()) |
| */ |
| private java.util.Random random = new java.util.Random(); |
| /** |
| * Expected amount of memory allocated during stress test |
| */ |
| private long stressAllocatedBytes; |
| /** |
| * Maximum memory in bytes that one thread is allowed to use at once |
| */ |
| private long maxThreadMemory = 0; |
| /** |
| * GarbageProducer for objects creation |
| */ |
| private GarbageProducer gp; |
| /** |
| * Stresser instance for allocateStress() |
| */ |
| private Stresser stresser; |
| |
| public static void warmUp(String garbageProducerId) { |
| MXBeanTestThread warmUpThread = new MXBeanTestThread(garbageProducerId) { |
| @Override |
| public void doWork() { |
| allocate(); |
| } |
| }; |
| warmUpThread.start(); |
| do { |
| try { |
| warmUpThread.join(); |
| } catch (InterruptedException ie) {} |
| } while(warmUpThread.isAlive()); |
| } |
| |
| /** |
| * Sets BarrierHandler for this thread |
| * |
| * @param handler BarrierHandler to synchronize with |
| */ |
| public void setHandler(BarrierHandler handler) { |
| this.handler = handler; |
| } |
| |
| /** |
| * Returns an instance of MXBeanTestThread with already defined |
| * allocatedList List and GarbageProducer |
| */ |
| public MXBeanTestThread(String garbageProducerId) { |
| super(Integer.toString(++threadCount)); |
| allocatedList = new ArrayList<Object>(); |
| gp = GarbageUtils.getGarbageProducer(garbageProducerId); |
| maxThreadMemory = Runtime.getRuntime().maxMemory()/4; |
| } |
| |
| /** |
| * Returns an instance of MXBeanTestThread with already defined |
| * allocatedList List and default GarbageProducer |
| */ |
| public MXBeanTestThread() { |
| this("intArr"); |
| } |
| |
| /** |
| * Returns an instance of MXBeanTestThread with already defined |
| * allocatedList List and Stresser |
| */ |
| public MXBeanTestThread(Stresser stresser) { |
| this("intArr"); |
| this.stresser = stresser; |
| } |
| |
| /** |
| * Sets maximum amount of memory that could be used at once for each |
| * TestThread in StressTest |
| */ |
| public void setMaxThreadMemory (long memory) { |
| maxThreadMemory = memory; |
| } |
| |
| /** |
| * Returns expected memory allocated by TestThread during StressTest |
| * @return expected memory amount |
| */ |
| public long getStressAllocatedBytes() { |
| return stressAllocatedBytes; |
| } |
| |
| @Override |
| public void run() { |
| doWork(); |
| } |
| |
| /** |
| * Implementation of TestThread behavior logic |
| */ |
| public void doWork() { |
| handler.ready(); |
| allocate(); |
| handler.ready(); |
| } |
| |
| /** |
| * Allocates memory for amount of time specified in Stresser instance |
| */ |
| protected void allocateStress() { |
| // Size of long[] array that allocates 2 Mb + 1 byte |
| int MAX_ARR_SIZE=262146; |
| // Anount of memory allocated by thread with existing links |
| // Which means that these objects can't be collected by GC |
| long actuallyAllocated = 0; |
| try { |
| while (stresser.continueExecution()) { |
| //int chunkSize = random.nextInt(MAX_OBJECT_SIZE); |
| //Object obj = gp.create(chunkSize); |
| int chunkSize = random.nextInt(MAX_ARR_SIZE); |
| Object obj = new long[chunkSize]; |
| allocatedList.add(obj); |
| actuallyAllocated += chunkSize*8; |
| if (actuallyAllocated > maxThreadMemory) { |
| // Allocated more then allowed to one thread |
| // re-define allocatedList to allow GC to delete |
| // created objects |
| stressAllocatedBytes += actuallyAllocated; |
| actuallyAllocated = 0; |
| allocatedList = new ArrayList<Object>(); |
| } |
| } |
| } catch (OutOfMemoryError e) { |
| } finally { |
| stressAllocatedBytes += actuallyAllocated; |
| } |
| } |
| |
| /** |
| * Allocates memory once according test settings |
| */ |
| protected void allocate() { |
| long actuallyAllocated = 0; |
| for (int i = 0; i < ThreadMXBeanTestBase.allocArr.length; i++) { |
| long size = ThreadMXBeanTestBase.allocArr[i]; |
| if (actuallyAllocated + size > maxThreadMemory) { |
| break; |
| } |
| allocatedList.add(gp.create(size)); |
| actuallyAllocated += size; |
| } |
| } |
| } |