blob: a15a67fc23adf0671ea9d6e32ff4bcdf4cb6cd70 [file] [log] [blame]
/*
* Copyright (c) 2003, 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/JumbleGC002.
* VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, quarantine]
* VM Testbase readme:
* DESCRIPTION
* The test checks that Garbage Collector can manage jumble in the JVM. The
* test fails if any unexpected exceptions and errors are thrown or the JVM
* is not crashed.
* The test starts a number of threads that is set in *.cfg file or calculates
* that value based on the machine. All threads have
* java.util.Vector field anf they fill that vector with 4 types of objects:
* 1. Initialized long[]
* 2. Uninitialized double[]
* 3. Initialized int[]
* 4. A nsk.share.gc.NonbranchyTree (number of nodes and their size depend
* on valkue returned by Runtime.maxMemory())
* As soon as the vector is filled, each thread removes half elements of it and
* then fills those places of the vector again. However, all threads use just
* about 10% of maximum amount of memory that JVM attemts to use, so
* OutOfMemoryError is treated as a failure. That means GC does not work
* quickly enough to destroy all objects that do not have references. The
* procedure of filling and cleaning of the vector is repeated for
* INTERNAL_ITERATIONS times.
*
* @library /vmTestbase
* /test/lib
* @run driver jdk.test.lib.FileInstaller . .
* @run main/othervm -XX:-UseGCOverheadLimit gc.gctests.JumbleGC002.JumbleGC002
*/
package gc.gctests.JumbleGC002;
import java.io.*;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import nsk.share.*;
import nsk.share.gc.*;
/**
* This test simply does Algorithms.eatMemory() in a loop
* in multiple threads.
*/
public class JumbleGC002 extends ThreadedGCTest {
// The test should fill just about 10% of the heap
final static double PART_OF_HEAP = 0.1;
// Maximum number of elements in an array of primitive types
final static int ARRAY_MAX_LENGTH = 10;
// Internal number of iterations to create new objects and to drop
// references
final static int INTERNAL_ITERATIONS = 150;
// Size of core for each node of a tree
final static int EACH_NODE_SIZE = 1;
// Number of bytes that arrays of primitive types take in the vector
final static long PRIMITIVE_ARRAYS_SIZE = (long) (8 * ARRAY_MAX_LENGTH
+ 8 * ARRAY_MAX_LENGTH + 4 * ARRAY_MAX_LENGTH);
private class Eater implements Runnable {
private Vector vector;
int numberOfElements;
int numberOfQuarters;
int id;
int nodes;
ThreadLocalRandom random = ThreadLocalRandom.current();
public Eater(int id, int numberOfQuarters, int nodes) {
this.numberOfQuarters = numberOfQuarters;
numberOfElements = 4 * numberOfQuarters;
this.id = id;
this.nodes = nodes;
}
public void run() {
// Make jumble in the heap!
initVector();
while (getExecutionController().continueExecution()) {
fillVector();
cleanVector();
}
}
// Initialize the vector and build appropriate number of cells in it
private void initVector() {
vector = new Vector();
for (int i = 0; i < numberOfElements; i++) {
vector.addElement(null);
}
}
// Fill the vector. It is devided into quarters. Each quarters has an
// initialized array of long and int, and uninitialized array of double.
// Each array has not more than ARRAY_MAX_LENGTH elements. The fourth
// element in the quarter is a NonbranchyTree.
private void fillVector() {
for (int i = 0; i < numberOfQuarters; i++) {
// Append initialized long[]
int length = random.nextInt(ARRAY_MAX_LENGTH);
long[] l = new long[length];
for (int j = 0; j < length; j++) {
l[j] = (long) j;
}
if (vector.elementAt(4 * i) == null) {
vector.setElementAt(l, 4 * i);
}
// Append not initialized double[]
length = random.nextInt(ARRAY_MAX_LENGTH);
double[] d = new double[length];
if (vector.elementAt(4 * i + 1) == null) {
vector.setElementAt(d, 4 * i + 1);
}
// Append initialized int[]
length = random.nextInt(ARRAY_MAX_LENGTH);
int[] n = new int[length];
for (int j = 0; j < length; j++) {
n[j] = j;
}
if (vector.elementAt(4 * i + 2) == null) {
vector.setElementAt(n, 4 * i + 2);
}
// Append a tree. Every even thread has a "bent" tree.
NonbranchyTree tree = new NonbranchyTree(nodes, 0.3f, EACH_NODE_SIZE);
if (id % 2 == 0) {
tree.bend();
}
if (vector.elementAt(4 * i + 3) == null) {
vector.setElementAt(tree, 4 * i + 3);
}
}
}
// Drop references to half of the elements of the vector
private void cleanVector() {
int index = random.nextInt(numberOfElements / 2);
for (int i = index; i < index + numberOfElements / 2; i++) {
vector.setElementAt(null, i);
}
}
}
protected Runnable createRunnable(int i) {
// Perform calculations specific to the test
long memoryForThread = (long) (Runtime.getRuntime().maxMemory() * PART_OF_HEAP / runParams.getNumberOfThreads());
int numberOfQuarters;
if (i == 0) {
// The very first thread
numberOfQuarters = 1;
} else {
// All other threads
numberOfQuarters = 8;
}
// Calculate number of nodes for a tree depending on number of
// elements in the Vector
double freeMemory = (double) memoryForThread / numberOfQuarters
- (double) PRIMITIVE_ARRAYS_SIZE;
int nodes = (int) (freeMemory / (NonbranchyTree.MIN_NODE_SIZE + EACH_NODE_SIZE));
nodes = Math.max(1, nodes);
log.debug("Thread " + i + " has a tree with "
+ nodes + " node(s).");
return new Eater(i, numberOfQuarters, nodes);
}
public static void main(String args[]) {
GC.runTest(new JumbleGC002(), args);
}
}