8205096: Add missing files for 8203394

Add files missed in the push for Low-Overhead Heap Profiling

Reviewed-by: dholmes, tschatzl, rehn, simonis, ehelin
This commit is contained in:
Jean Christophe Beyler 2018-06-15 02:31:37 -07:00
parent 6129ed590c
commit 89453e7c64
28 changed files with 3163 additions and 0 deletions

View File

@ -0,0 +1,188 @@
/*
* Copyright (c) 2018, Google 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.
*
*/
#include "precompiled.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/orderAccess.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/threadHeapSampler.hpp"
// Cheap random number generator
uint64_t ThreadHeapSampler::_rnd;
// Default is 512kb.
int ThreadHeapSampler::_sampling_rate = 512 * 1024;
int ThreadHeapSampler::_enabled;
// Statics for the fast log
static const int FastLogNumBits = 10;
static const int FastLogMask = (1 << FastLogNumBits) - 1;
static double log_table[1<<FastLogNumBits]; // Constant
static bool log_table_initialized;
// Returns the next prng value.
// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48
// This is the lrand64 generator.
static uint64_t next_random(uint64_t rnd) {
const uint64_t PrngMult = 0x5DEECE66DLL;
const uint64_t PrngAdd = 0xB;
const uint64_t PrngModPower = 48;
const uint64_t PrngModMask = right_n_bits(PrngModPower);
//assert(IS_SAFE_SIZE_MUL(PrngMult, rnd), "Overflow on multiplication.");
//assert(IS_SAFE_SIZE_ADD(PrngMult * rnd, PrngAdd), "Overflow on addition.");
return (PrngMult * rnd + PrngAdd) & PrngModMask;
}
static double fast_log2(const double & d) {
assert(d>0, "bad value passed to assert");
uint64_t x = 0;
assert(sizeof(d) == sizeof(x),
"double and uint64_t do not have the same size");
x = *reinterpret_cast<const uint64_t*>(&d);
const uint32_t x_high = x >> 32;
assert(FastLogNumBits <= 20, "FastLogNumBits should be less than 20.");
const uint32_t y = x_high >> (20 - FastLogNumBits) & FastLogMask;
const int32_t exponent = ((x_high >> 20) & 0x7FF) - 1023;
return exponent + log_table[y];
}
// Generates a geometric variable with the specified mean (512K by default).
// This is done by generating a random number between 0 and 1 and applying
// the inverse cumulative distribution function for an exponential.
// Specifically: Let m be the inverse of the sample rate, then
// the probability distribution function is m*exp(-mx) so the CDF is
// p = 1 - exp(-mx), so
// q = 1 - p = exp(-mx)
// log_e(q) = -mx
// -log_e(q)/m = x
// log_2(q) * (-log_e(2) * 1/m) = x
// In the code, q is actually in the range 1 to 2**26, hence the -26 below
void ThreadHeapSampler::pick_next_geometric_sample() {
_rnd = next_random(_rnd);
// Take the top 26 bits as the random number
// (This plus a 1<<58 sampling bound gives a max possible step of
// 5194297183973780480 bytes. In this case,
// for sample_parameter = 1<<19, max possible step is
// 9448372 bytes (24 bits).
const uint64_t PrngModPower = 48; // Number of bits in prng
// The uint32_t cast is to prevent a (hard-to-reproduce) NAN
// under piii debug for some binaries.
double q = static_cast<uint32_t>(_rnd >> (PrngModPower - 26)) + 1.0;
// Put the computed p-value through the CDF of a geometric.
// For faster performance (save ~1/20th exec time), replace
// min(0.0, FastLog2(q) - 26) by (Fastlog2(q) - 26.000705)
// The value 26.000705 is used rather than 26 to compensate
// for inaccuracies in FastLog2 which otherwise result in a
// negative answer.
double log_val = (fast_log2(q) - 26);
double result =
(0.0 < log_val ? 0.0 : log_val) * (-log(2.0) * (get_sampling_rate())) + 1;
assert(result > 0 && result < SIZE_MAX, "Result is not in an acceptable range.");
size_t rate = static_cast<size_t>(result);
_bytes_until_sample = rate;
}
void ThreadHeapSampler::pick_next_sample(size_t overflowed_bytes) {
if (get_sampling_rate() == 1) {
_bytes_until_sample = 1;
return;
}
pick_next_geometric_sample();
// Try to correct sample size by removing extra space from last allocation.
if (overflowed_bytes > 0 && _bytes_until_sample > overflowed_bytes) {
_bytes_until_sample -= overflowed_bytes;
}
}
void ThreadHeapSampler::check_for_sampling(HeapWord* ptr, size_t allocation_size, size_t bytes_since_allocation) {
oopDesc* oop = reinterpret_cast<oopDesc*>(ptr);
size_t total_allocated_bytes = bytes_since_allocation + allocation_size;
// If not yet time for a sample, skip it.
if (total_allocated_bytes < _bytes_until_sample) {
_bytes_until_sample -= total_allocated_bytes;
return;
}
JvmtiExport::sampled_object_alloc_event_collector(oop);
size_t overflow_bytes = total_allocated_bytes - _bytes_until_sample;
pick_next_sample(overflow_bytes);
}
void ThreadHeapSampler::init_log_table() {
MutexLockerEx mu(ThreadHeapSampler_lock, Mutex::_no_safepoint_check_flag);
if (log_table_initialized) {
return;
}
for (int i = 0; i < (1 << FastLogNumBits); i++) {
log_table[i] = (log(1.0 + static_cast<double>(i+0.5) / (1 << FastLogNumBits))
/ log(2.0));
}
log_table_initialized = true;
}
void ThreadHeapSampler::enable() {
// Done here to be done when things have settled. This adds a mutex lock but
// presumably, users won't be enabling and disabling all the time.
init_log_table();
OrderAccess::release_store(&_enabled, 1);
}
int ThreadHeapSampler::enabled() {
return OrderAccess::load_acquire(&_enabled);
}
void ThreadHeapSampler::disable() {
OrderAccess::release_store(&_enabled, 0);
}
int ThreadHeapSampler::get_sampling_rate() {
return OrderAccess::load_acquire(&_sampling_rate);
}
void ThreadHeapSampler::set_sampling_rate(int sampling_rate) {
OrderAccess::release_store(&_sampling_rate, sampling_rate);
}
// Methods used in assertion mode to check if a collector is present or not at
// the moment of TLAB sampling, ie a slow allocation path.
bool ThreadHeapSampler::sampling_collector_present() const {
return _collectors_present > 0;
}
bool ThreadHeapSampler::remove_sampling_collector() {
assert(_collectors_present > 0, "Problem with collector counter.");
_collectors_present--;
return true;
}
bool ThreadHeapSampler::add_sampling_collector() {
_collectors_present++;
return true;
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2018, Google 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.
*
*/
#ifndef RUNTIME_THREADHEAPSAMPLER_HPP
#define RUNTIME_THREADHEAPSAMPLER_HPP
#include "memory/allocation.hpp"
class ThreadHeapSampler {
private:
size_t _bytes_until_sample;
// Cheap random number generator
static uint64_t _rnd;
void pick_next_geometric_sample();
void pick_next_sample(size_t overflowed_bytes = 0);
static int _enabled;
static int _sampling_rate;
// Used for assertion mode to determine if there is a path to a TLAB slow path
// without a collector present.
size_t _collectors_present;
static void init_log_table();
public:
ThreadHeapSampler() : _bytes_until_sample(0) {
_rnd = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this));
if (_rnd == 0) {
_rnd = 1;
}
_collectors_present = 0;
}
size_t bytes_until_sample() { return _bytes_until_sample; }
void set_bytes_until_sample(size_t bytes) { _bytes_until_sample = bytes; }
void check_for_sampling(HeapWord* obj, size_t size_in_bytes, size_t bytes_allocated_before = 0);
static int enabled();
static void enable();
static void disable();
static void set_sampling_rate(int sampling_rate);
static int get_sampling_rate();
bool sampling_collector_present() const;
bool remove_sampling_collector();
bool add_sampling_collector();
};
#endif // SHARE_RUNTIME_THREADHEAPSAMPLER_HPP

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
class Frame {
Frame(String method, String signature, String fileName, int lineNumber) {
this.method = method;
this.signature = signature;
this.fileName = fileName;
this.lineNumber = lineNumber;
}
public String method;
public String signature;
public String fileName;
public int lineNumber;
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.ArrayList;
import java.util.List;
/** API for handling the underlying heap sampling monitoring system. */
public class HeapMonitor {
private static int[][] arrays;
private static int allocationIterations = 1000;
static {
try {
System.loadLibrary("HeapMonitorTest");
} catch (UnsatisfiedLinkError ule) {
System.err.println("Could not load HeapMonitor library");
System.err.println("java.library.path: " + System.getProperty("java.library.path"));
throw ule;
}
}
/** Set a specific sampling rate, 0 samples every allocation. */
public native static void setSamplingRate(int rate);
public native static void enableSamplingEvents();
public native static boolean enableSamplingEventsForTwoThreads(Thread firstThread, Thread secondThread);
public native static void disableSamplingEvents();
/**
* Allocate memory but first create a stack trace.
*
* @return list of frames for the allocation.
*/
public static List<Frame> allocate() {
int sum = 0;
List<Frame> frames = new ArrayList<Frame>();
allocate(frames);
frames.add(new Frame("allocate", "()Ljava/util/List;", "HeapMonitor.java", 58));
return frames;
}
private static void allocate(List<Frame> frames) {
int sum = 0;
for (int j = 0; j < allocationIterations; j++) {
sum += actuallyAllocate();
}
frames.add(new Frame("actuallyAllocate", "()I", "HeapMonitor.java", 93));
frames.add(new Frame("allocate", "(Ljava/util/List;)V", "HeapMonitor.java", 66));
}
public static List<Frame> repeatAllocate(int max) {
List<Frame> frames = null;
for (int i = 0; i < max; i++) {
frames = allocate();
}
frames.add(new Frame("repeatAllocate", "(I)Ljava/util/List;", "HeapMonitor.java", 75));
return frames;
}
private static int actuallyAllocate() {
int sum = 0;
// Let us assume that a 1-element array is 24 bytes of memory and we want
// 2MB allocated.
int iterations = (1 << 19) / 6;
if (arrays == null) {
arrays = new int[iterations][];
}
for (int i = 0; i < iterations; i++) {
int tmp[] = new int[1];
// Force it to be kept and, at the same time, wipe out any previous data.
arrays[i] = tmp;
sum += arrays[0][0];
}
return sum;
}
public static int allocateSize(int totalSize) {
int sum = 0;
// Let us assume that a 1-element array is 24 bytes.
int iterations = totalSize / 24;
if (arrays == null) {
arrays = new int[iterations][];
}
System.out.println("Allocating for " + iterations);
for (int i = 0; i < iterations; i++) {
int tmp[] = new int[1];
// Force it to be kept and, at the same time, wipe out any previous data.
arrays[i] = tmp;
sum += arrays[0][0];
}
return sum;
}
/** Remove the reference to the global array to free data at the next GC. */
public static void freeStorage() {
arrays = null;
}
public static int[][][] sampleEverything() {
enableSamplingEvents();
setSamplingRate(0);
// Loop around an allocation loop and wait until the tlabs have settled.
final int maxTries = 10;
int[][][] result = new int[maxTries][][];
for (int i = 0; i < maxTries; i++) {
final int maxInternalTries = 400;
result[i] = new int[maxInternalTries][];
resetEventStorage();
for (int j = 0; j < maxInternalTries; j++) {
final int size = 1000;
result[i][j] = new int[size];
}
int sampledEvents = sampledEvents();
if (sampledEvents == maxInternalTries) {
return result;
}
}
throw new RuntimeException("Could not set the sampler");
}
public native static int sampledEvents();
public native static boolean obtainedEvents(Frame[] frames);
public native static boolean garbageContains(Frame[] frames);
public native static boolean eventStorageIsEmpty();
public native static void resetEventStorage();
public native static int getEventStorageElementCount();
public native static void forceGarbageCollection();
public native static boolean enableVMEvents();
public static boolean statsHaveExpectedNumberSamples(int expected, int acceptedErrorPercentage) {
double actual = getEventStorageElementCount();
double diffPercentage = Math.abs(actual - expected) / expected;
return diffPercentage < acceptedErrorPercentage;
}
public static void setAllocationIterations(int iterations) {
allocationIterations = iterations;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the JVMTI Heap Monitor rate when allocating arrays.
* @compile HeapMonitorArrayAllSampledTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorArrayAllSampledTest
*/
public class HeapMonitorArrayAllSampledTest {
// Do 1000 iterations and expect maxIteration samples.
private static final int maxIteration = 1000;
private static int array[];
private static void allocate(int size) {
for (int j = 0; j < maxIteration; j++) {
array = new int[size];
}
}
public static void main(String[] args) {
int sizes[] = {1000, 10000, 100000, 1000000};
HeapMonitor.setSamplingRate(0);
HeapMonitor.enableSamplingEvents();
for (int currentSize : sizes) {
System.out.println("Testing size " + currentSize);
HeapMonitor.resetEventStorage();
allocate(currentSize);
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
// statistical geometric variable around the sampling rate. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples(maxIteration, 10)) {
throw new RuntimeException("Statistics should show about " + maxIteration + " samples.");
}
}
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.List;
/**
* @test
* @summary Verifies if turning off the event notification stops events.
* @build Frame HeapMonitor
* @compile HeapMonitorEventOnOffTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorEventOnOffTest
*/
public class HeapMonitorEventOnOffTest {
private static void checkNoEventsAreBeingSent() {
HeapMonitor.resetEventStorage();
HeapMonitor.repeatAllocate(5);
// Check that the data is not available while heap sampling is disabled.
boolean status = HeapMonitor.eventStorageIsEmpty();
if (!status) {
throw new RuntimeException("Storage is not empty after allocating with disabled events.");
}
}
private static void checkEventsAreBeingSent() {
List<Frame> frameList = HeapMonitor.repeatAllocate(5);
frameList.add(new Frame("checkEventsAreBeingSent", "()V", "HeapMonitorEventOnOffTest.java", 48));
Frame[] frames = frameList.toArray(new Frame[0]);
// Check that the data is available while heap sampling is enabled.
boolean status = HeapMonitor.obtainedEvents(frames);
if (!status) {
throw new RuntimeException("Failed to find the traces after allocating with enabled events.");
}
}
public static void main(String[] args) {
HeapMonitor.enableSamplingEvents();
checkEventsAreBeingSent();
// Disabling the notification system should stop events.
HeapMonitor.disableSamplingEvents();
checkNoEventsAreBeingSent();
// Enabling the notification system should start events again.
HeapMonitor.enableSamplingEvents();
checkEventsAreBeingSent();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor ThreadInformation
* @summary Ensures the JVMTI Heap Monitor is not thread enable (test to change when it becomes so)
* @compile HeapMonitorEventsForTwoThreadsTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorEventsForTwoThreadsTest
*/
import java.util.List;
public class HeapMonitorEventsForTwoThreadsTest {
public native static boolean checkSamples();
public static void main(String[] args) {
final int numThreads = 24;
List<ThreadInformation> threadList = ThreadInformation.createThreadList(numThreads);
Thread firstThread = threadList.get(0).getThread();
Thread secondThread = threadList.get(1).getThread();
if (HeapMonitor.enableSamplingEventsForTwoThreads(firstThread, secondThread)) {
throw new RuntimeException("Sampling event is thread enabled, that is unexpected.");
}
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor Statistics using CMS GC
* @build Frame HeapMonitor
* @requires vm.gc == "ConcMarkSweep" | vm.gc == "null"
* @compile HeapMonitorGCCMSTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest -XX:+UseConcMarkSweepGC MyPackage.HeapMonitorGCTest
*/

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor Statistics using ParallelGc
* @build Frame HeapMonitor
* @compile HeapMonitorGCTest.java
* @requires vm.gc == "Parallel" | vm.gc == "null"
* @run main/othervm/native -agentlib:HeapMonitorTest -XX:+UseParallelGC MyPackage.HeapMonitorGCTest
*/

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor Statistics using SerialGC
* @build Frame HeapMonitor
* @compile HeapMonitorGCTest.java
* @requires vm.gc == "Serial" | vm.gc == "null"
* @run main/othervm/native -agentlib:HeapMonitorTest -XX:+UseSerialGC MyPackage.HeapMonitorGCTest
*/

View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.List;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the default GC with the Heap Monitor event system.
* @compile HeapMonitorGCTest.java
* @requires vm.gc == "G1" | vm.gc == "null"
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorGCTest
*/
/**
* This test is checking that various GCs work as intended: events are sent, forcing GC works, etc.
*/
public class HeapMonitorGCTest {
public static void main(String[] args) {
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Statistics should be null to begin with.");
}
HeapMonitor.enableSamplingEvents();
List<Frame> frameList = HeapMonitor.allocate();
frameList.add(new Frame("main", "([Ljava/lang/String;)V", "HeapMonitorGCTest.java", 48));
Frame[] frames = frameList.toArray(new Frame[0]);
if (!HeapMonitor.obtainedEvents(frames)) {
throw new RuntimeException("No expected events were found.");
}
HeapMonitor.forceGarbageCollection();
if (!HeapMonitor.garbageContains(frames)) {
throw new RuntimeException("Forcing GC did not work, not a single object was collected.");
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI SetHeapSamplingRate returns an illegal argument for negative ints.
* @build Frame HeapMonitor
* @compile HeapMonitorIllegalArgumentTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorIllegalArgumentTest
*/
public class HeapMonitorIllegalArgumentTest {
private native static int testIllegalArgument();
public static void main(String[] args) {
int result = testIllegalArgument();
if (result == 0) {
throw new RuntimeException("Test illegal argument failed.");
}
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor using the interpreter.
* @build Frame HeapMonitor
* @compile HeapMonitorTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest -Xint MyPackage.HeapMonitorTest 10
*/

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor using the interpreter.
* @build Frame HeapMonitor
* @compile HeapMonitorStatObjectCorrectnessTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest -Xint MyPackage.HeapMonitorStatObjectCorrectnessTest
*/

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.List;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor API when allocating a multi-array.
* @build Frame HeapMonitor
* @compile HeapMonitorMultiArrayTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorMultiArrayTest
*/
public class HeapMonitorMultiArrayTest {
private static int[][] tab;
public static void main(String[] args) throws Exception {
// Set ourselves to sample everything.
HeapMonitor.sampleEverything();
// Do a few allocations now and see if the callback happens and the program finishes:
HeapMonitor.resetEventStorage();
int iterations = 1000;
int allocationsPerIteration = 6;
for (int i = 0; i < iterations; i++) {
tab = new int[5][5];
}
int sampledEvents = HeapMonitor.sampledEvents();
int expectedNumber = iterations * allocationsPerIteration;
if (sampledEvents != expectedNumber) {
throw new RuntimeException("Number of samples (" + sampledEvents + ") not the expected ("
+ expectedNumber + ")");
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor does not work without the required capability.
* @build Frame HeapMonitor
* @compile HeapMonitorNoCapabilityTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorNoCapabilityTest
*/
public class HeapMonitorNoCapabilityTest {
private native static int allSamplingMethodsFail();
public static void main(String[] args) {
int result = allSamplingMethodsFail();
if (result == 0) {
throw new RuntimeException("Some methods could be called without a capability.");
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.List;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor API does not do infinite recursion.
* @build Frame HeapMonitor
* @compile HeapMonitorRecursiveTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorRecursiveTest
*/
public class HeapMonitorRecursiveTest {
private native static void setCallbackToCallAllocateSomeMore();
private native static boolean didCallback();
private static int[] tab;
public static void main(String[] args) throws Exception {
// Set ourselves to sample everything.
HeapMonitor.sampleEverything();
// Set a callback that does allocate more data. If a callback's allocations get sampled, this
// would do an infinite recursion.
setCallbackToCallAllocateSomeMore();
// Do a few allocations now and see if the callback happens and the program finishes:
for (int i = 0; i < 1000; i++) {
tab = new int[1024];
}
if (!didCallback()) {
throw new RuntimeException("Did not get a callback...");
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the JVMTI Heap Monitor rate when allocating arrays.
* @compile HeapMonitorStatArrayCorrectnessTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatArrayCorrectnessTest
*/
public class HeapMonitorStatArrayCorrectnessTest {
// Do 100000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 100000;
private static int array[];
private static void allocate(int size) {
for (int j = 0; j < maxIteration; j++) {
array = new int[size];
}
}
public static void main(String[] args) {
int sizes[] = {1000, 10000, 100000};
HeapMonitor.enableSamplingEvents();
for (int currentSize : sizes) {
System.out.println("Testing size " + currentSize);
HeapMonitor.resetEventStorage();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Should not have any events stored yet.");
}
// 111 is as good a number as any.
final int samplingMultiplier = 111;
HeapMonitor.setSamplingRate(samplingMultiplier * currentSize);
allocate(currentSize);
// For simplifications, we ignore the array memory usage for array internals (with the array
// sizes requested, it should be a negligible oversight).
//
// That means that with maxIterations, the loop in the method allocate requests:
// maxIterations * currentSize * 4 bytes (4 for integers)
//
// Via the enable sampling, the code requests a sample every samplingMultiplier * currentSize bytes.
//
// Therefore, the expected sample number is:
// (maxIterations * currentSize * 4) / (samplingMultiplier * currentSize);
double expected = maxIteration;
expected *= 4;
expected /= samplingMultiplier;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
// statistical geometric variable around the sampling rate. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
throw new RuntimeException("Statistics should show about " + expected + " samples.");
}
}
}
}

View File

@ -0,0 +1,145 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the JVMTI Heap Monitor sampling via object allocation.
* @compile HeapMonitorStatObjectCorrectnessTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatObjectCorrectnessTest
*/
/** This test is checking the object allocation path works with heap sampling. */
public class HeapMonitorStatObjectCorrectnessTest {
// Do 200000 iterations and expect maxIteration / multiplier samples.
private static final int maxIteration = 200000;
private static BigObject obj;
private native static boolean statsHaveExpectedNumberSamples(int expected, int percentError);
private static void allocate() {
for (int j = 0; j < maxIteration; j++) {
obj = new BigObject();
}
}
private static void testBigAllocationRate() {
final int sizeObject = 1400;
// 111 is as good a number as any.
final int samplingMultiplier = 111;
HeapMonitor.setSamplingRate(samplingMultiplier * sizeObject);
emptyStorage();
allocate();
// For simplifications, the code is allocating:
// (BigObject size) * maxIteration.
//
// We ignore the class memory usage apart from field memory usage for BigObject. BigObject
// allocates 250 long, so 2000 bytes, so whatever is used for the class is negligible.
//
// That means that with maxIterations, the loop in the method allocate requests:
// maxIterations * 2000 bytes.
//
// Via the enable sampling, the code requests a sample every samplingMultiplier * sizeObject bytes.
//
// Therefore, the expected sample number is:
// (maxIterations * sizeObject) / (samplingMultiplier * sizeObject);
//
// Which becomes:
// maxIterations / samplingMultiplier
double expected = maxIteration;
expected /= samplingMultiplier;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
// statistical geometric variable around the sampling rate. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
throw new RuntimeException("Statistics should show about " + expected + " samples.");
}
}
private static void emptyStorage() {
HeapMonitor.resetEventStorage();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Statistics should be null to begin with.");
}
}
private static void testEveryAllocationSampled() {
// 0 means sample every allocation.
HeapMonitor.setSamplingRate(0);
emptyStorage();
allocate();
double expected = maxIteration;
// 10% error ensures a sanity test without becoming flaky.
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
// statistical geometric variable around the sampling rate. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
throw new RuntimeException("Statistics should show about " + expected + " samples.");
}
}
public static void main(String[] args) {
HeapMonitor.enableSamplingEvents();
testBigAllocationRate();
testEveryAllocationSampled();
}
/**
* Big class on purpose to just be able to ignore the class memory space overhead.
*
* Class contains 175 long fields, so 175 * 8 = 1400 bytes.
*/
private static class BigObject {
private long a0_0, a0_1, a0_2, a0_3, a0_4, a0_5, a0_6, a0_7, a0_8, a0_9;
private long a1_0, a1_1, a1_2, a1_3, a1_4, a1_5, a1_6, a1_7, a1_8, a1_9;
private long a2_0, a2_1, a2_2, a2_3, a2_4, a2_5, a2_6, a2_7, a2_8, a2_9;
private long a3_0, a3_1, a3_2, a3_3, a3_4, a3_5, a3_6, a3_7, a3_8, a3_9;
private long a4_0, a4_1, a4_2, a4_3, a4_4, a4_5, a4_6, a4_7, a4_8, a4_9;
private long a5_0, a5_1, a5_2, a5_3, a5_4, a5_5, a5_6, a5_7, a5_8, a5_9;
private long a6_0, a6_1, a6_2, a6_3, a6_4, a6_5, a6_6, a6_7, a6_8, a6_9;
private long a7_0, a7_1, a7_2, a7_3, a7_4, a7_5, a7_6, a7_7, a7_8, a7_9;
private long a8_0, a8_1, a8_2, a8_3, a8_4, a8_5, a8_6, a8_7, a8_8, a8_9;
private long a9_0, a9_1, a9_2, a9_3, a9_4, a9_5, a9_6, a9_7, a9_8, a9_9;
private long a10_0, a10_1, a10_2, a10_3, a10_4, a10_5, a10_6, a10_7, a10_8, a10_9;
private long a11_0, a11_1, a11_2, a11_3, a11_4, a11_5, a11_6, a11_7, a11_8, a11_9;
private long a12_0, a12_1, a12_2, a12_3, a12_4, a12_5, a12_6, a12_7, a12_8, a12_9;
private long a13_0, a13_1, a13_2, a13_3, a13_4, a13_5, a13_6, a13_7, a13_8, a13_9;
private long a14_0, a14_1, a14_2, a14_3, a14_4, a14_5, a14_6, a14_7, a14_8, a14_9;
private long a15_0, a15_1, a15_2, a15_3, a15_4, a15_5, a15_6, a15_7, a15_8, a15_9;
private long a16_0, a16_1, a16_2, a16_3, a16_4, a16_5, a16_6, a16_7, a16_8, a16_9;
private long a17_0, a17_1, a17_2, a17_3, a17_4;
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor sampling rate average.
* @build Frame HeapMonitor
* @compile HeapMonitorStatRateTest.java
* @requires vm.compMode != "Xcomp"
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatRateTest
*/
public class HeapMonitorStatRateTest {
private native static double getAverageRate();
private static boolean testRateOnce(int rate, boolean throwIfFailure) {
HeapMonitor.resetEventStorage();
HeapMonitor.setSamplingRate(rate);
HeapMonitor.enableSamplingEvents();
int allocationTotal = 10 * 1024 * 1024;
HeapMonitor.allocateSize(allocationTotal);
HeapMonitor.disableSamplingEvents();
double actualCount = HeapMonitor.getEventStorageElementCount();
double expectedCount = allocationTotal / rate;
double error = Math.abs(actualCount - expectedCount);
double errorPercentage = error / expectedCount * 100;
boolean failure = (errorPercentage > 10.0);
if (failure && throwIfFailure) {
throw new RuntimeException("Rate average over 10% for rate " + rate + " -> " + actualCount
+ ", " + expectedCount);
}
return failure;
}
private static void testRate(int rate) {
// Test the rate twice, it can happen that the test is "unlucky" and the rate just goes above
// the 10% mark. So try again to squash flakiness.
// Flakiness is due to the fact that this test is dependent on the sampling rate, which is a
// statistical geometric variable around the sampling rate. This means that the test could be
// unlucky and not achieve the mean average fast enough for the test case.
if (!testRateOnce(rate, false)) {
testRateOnce(rate, true);
}
}
public static void main(String[] args) {
int[] tab = {1024, 8192};
for (int rateIdx = 0; rateIdx < tab.length; rateIdx++) {
testRate(tab[rateIdx]);
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the JVMTI Heap Monitor events are only sent after enabling.
* @compile HeapMonitorStatSimpleTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatSimpleTest
*/
public class HeapMonitorStatSimpleTest {
private native static int areSamplingStatisticsZero();
public static void main(String[] args) {
HeapMonitor.allocate();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Statistics should be null to begin with.");
}
HeapMonitor.enableSamplingEvents();
HeapMonitor.allocate();
if (HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Statistics should not be null now.");
}
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.List;
/**
* @test
* @summary Verifies the JVMTI Heap Monitor API
* @build Frame HeapMonitor
* @compile HeapMonitorTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorTest
*/
public class HeapMonitorTest {
private static native boolean framesAreNotLive(Frame[] frames);
public static void main(String[] args) {
if (args.length > 0) {
// For interpreter mode, have a means to reduce the default iteration count.
HeapMonitor.setAllocationIterations(Integer.parseInt(args[0]));
}
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Storage is not empty at test start...");
}
HeapMonitor.enableSamplingEvents();
List<Frame> frameList = HeapMonitor.allocate();
frameList.add(new Frame("main", "([Ljava/lang/String;)V", "HeapMonitorTest.java", 51));
Frame[] frames = frameList.toArray(new Frame[0]);
if (!HeapMonitor.obtainedEvents(frames)) {
throw new RuntimeException("Events not found with the right frames.");
}
HeapMonitor.disableSamplingEvents();
HeapMonitor.resetEventStorage();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Storage is not empty after reset.");
}
HeapMonitor.allocate();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Storage is not empty after allocation while disabled.");
}
}
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor
* @summary Verifies the JVMTI Heap Monitor Thread sanity.
* @compile HeapMonitorThreadOnOffTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorThreadOnOffTest
*/
import java.util.ArrayList;
import java.util.List;
public class HeapMonitorThreadOnOffTest {
public static void main(String[] args) {
final int numThreads = 24;
ArrayList<Thread> list = new ArrayList<>();
// Add one thread that consistently turns on/off the sampler to ensure correctness with
// potential resets.
Switch switchPlayer = new Switch();
Thread switchThread = new Thread(switchPlayer, "Switch Player");
switchThread.start();
for (int i = 0 ; i < numThreads; i++) {
Thread thread = new Thread(new Allocator(i), "Allocator" + i);
thread.start();
list.add(thread);
}
for (Thread elem : list) {
try {
elem.join();
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted...");
}
}
switchPlayer.stop();
try {
switchThread.join();
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted while waiting for the switch player...");
}
// We don't check here for correctness of data. If we made it here, the test succeeded:
// Threads can allocate like crazy
// Other threads can turn on/off the system
}
}
class Allocator implements Runnable {
private int depth;
private volatile int tmp[];
public Allocator(int depth) {
this.depth = depth;
}
private int helper() {
int sum = 0;
// Let us assume that the array is 24 bytes of memory.
for (int i = 0; i < 127000 / 6; i++) {
int newTmp[] = new int[1];
// Force it to be kept.
tmp = newTmp;
sum += tmp[0];
}
return sum;
}
private int recursiveWrapper(int depth) {
if (depth > 0) {
return recursiveWrapper(depth - 1);
}
return helper();
}
public void run() {
int sum = 0;
for (int j = 0; j < 100; j++) {
sum += recursiveWrapper(depth);
}
}
}
class Switch implements Runnable {
private volatile boolean keepGoing;
public Switch() {
keepGoing = true;
}
public void stop() {
keepGoing = false;
}
public void run() {
while (keepGoing) {
HeapMonitor.disableSamplingEvents();
HeapMonitor.resetEventStorage();
HeapMonitor.enableSamplingEvents();
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor ThreadInformation
* @summary Verifies the JVMTI Heap Monitor Thread information sanity.
* @compile HeapMonitorThreadTest.java
* @run main/othervm/native -Xmx512m -agentlib:HeapMonitorTest MyPackage.HeapMonitorThreadTest
* @requires !vm.gc.Z
*/
import java.util.List;
public class HeapMonitorThreadTest {
private native static boolean checkSamples(int numThreads);
public static void main(String[] args) {
final int numThreads = 5;
List<ThreadInformation> threadList = ThreadInformation.createThreadList(numThreads);
// Sample at a rate of 8k.
HeapMonitor.setSamplingRate(1 << 13);
HeapMonitor.enableSamplingEvents();
System.err.println("Starting threads");
ThreadInformation.startThreads(threadList);
ThreadInformation.waitForThreads(threadList);
System.err.println("Waited for threads");
if (!checkSamples(numThreads)) {
throw new RuntimeException("Problem with checkSamples...");
}
// Now inform each thread we are done and wait for them to be done.
ThreadInformation.stopThreads(threadList);
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
/**
* @test
* @build Frame HeapMonitor ThreadInformation
* @summary Verifies the JVMTI Heap Monitor does not work with two agents.
* @compile HeapMonitorTwoAgentsTest.java
* @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorTwoAgentsTest
*/
import java.util.List;
public class HeapMonitorTwoAgentsTest {
private native static boolean enablingSamplingInSecondaryAgent();
private native static boolean obtainedEventsForBothAgents(Frame[] frames);
public static void main(String[] args) {
HeapMonitor.enableSamplingEvents();
if (enablingSamplingInSecondaryAgent()) {
throw new RuntimeException("Enabling sampling in second agent succeeded...");
}
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.ArrayList;
import java.util.List;
/**
* @test
* @summary Verifies that when the VM event is sent, sampled events are also collected.
* @build Frame HeapMonitor
* @compile HeapMonitorVMEventsTest.java
* @run main/othervm/native -XX:+UnlockDiagnosticVMOptions
* -XX:DisableIntrinsic=_clone
* -agentlib:HeapMonitorTest MyPackage.HeapMonitorVMEventsTest
*/
public class HeapMonitorVMEventsTest implements Cloneable {
private static native int vmEvents();
private static final int ITERATIONS = 1 << 15;
private static final Object[] array = new Object[ITERATIONS];
private static void cloneObjects(int iterations) {
HeapMonitorVMEventsTest object = new HeapMonitorVMEventsTest();
for (int i = 0; i < iterations; i++) {
try {
array[i] = object.clone();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
private static void checkDifference(int first, int second) {
double diff = Math.abs(first - second) * 100;
diff /= first;
// Accept a 10% error rate: with objects being allocated: this allows a bit of room in
// case other items are getting allocated during the test.
if (diff > 10) {
throw new RuntimeException("Error rate is over the accepted rate: " + diff
+ ": " + first + " , " + second);
}
}
private static void compareSampledAndVM() {
HeapMonitor.resetEventStorage();
cloneObjects(ITERATIONS);
int onlySampleCount = HeapMonitor.sampledEvents();
HeapMonitor.enableVMEvents();
HeapMonitor.resetEventStorage();
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Storage is not empty after reset.");
}
cloneObjects(ITERATIONS);
int sampleCount = HeapMonitor.sampledEvents();
int vmCount = vmEvents();
System.err.println("Obtained: " + onlySampleCount + " - " + sampleCount + " - " + vmCount);
checkDifference(onlySampleCount, sampleCount);
checkDifference(onlySampleCount, vmCount);
}
public static void main(String[] args) {
if (!HeapMonitor.eventStorageIsEmpty()) {
throw new RuntimeException("Storage is not empty at test start...");
}
HeapMonitor.sampleEverything();
compareSampledAndVM();
}
}

View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 2018, Google 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 MyPackage;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/** API for handling heap allocating threads. */
class ThreadInformation {
private Thread thread;
private Allocator allocator;
public ThreadInformation(Thread thread, Allocator allocator) {
this.thread = thread;
this.allocator = allocator;
}
public void waitForJobDone() {
allocator.waitForJobDone();
}
public void stop() {
try {
allocator.stopRun();
thread.join();
if (!allocator.endedNormally()) {
throw new RuntimeException("Thread did not end normally...");
}
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted...");
}
}
private void start() {
allocator.start();
}
public static void startThreads(List<ThreadInformation> threadList) {
for (ThreadInformation info : threadList) {
info.start();
}
}
public static void stopThreads(List<ThreadInformation> threadList) {
for (ThreadInformation info : threadList) {
info.stop();
}
}
public Thread getThread() {
return thread;
}
public static void waitForThreads(List<ThreadInformation> threadList) {
System.err.println("Waiting for threads to be done");
// Wait until all threads have put an object in the queue.
for (ThreadInformation info : threadList) {
info.waitForJobDone();
}
}
public static List<ThreadInformation> createThreadList(int numThreads) {
List<ThreadInformation> threadList = new ArrayList<>();
for (int i = 0 ; i < numThreads; i++) {
Allocator allocator = new Allocator(i);
Thread thread = new Thread(allocator, "Allocator" + i);
ThreadInformation info = new ThreadInformation(thread, allocator);
threadList.add(info);
thread.start();
}
return threadList;
}
}
class Allocator implements Runnable {
private int depth;
private List<int[]> currentList;
private BlockingQueue<Object> jobCanStart;
private BlockingQueue<Object> jobDone;
private BlockingQueue<Object> jobCanStop;
private boolean failed;
public Allocator(int depth) {
this.jobCanStart = new LinkedBlockingQueue<>();
this.jobDone = new LinkedBlockingQueue<>();
this.jobCanStop = new LinkedBlockingQueue<>();
this.depth = depth;
}
public boolean endedNormally() {
return !failed;
}
private void helper() {
List<int[]> newList = new ArrayList<>();
// Let us assume that the array is 40 bytes of memory, keep in
// memory at least 1.7MB without counting the link-list itself, which adds to this.
int iterations = (1 << 20) / 24;
for (int i = 0; i < iterations; i++) {
int newTmp[] = new int[5];
// Force it to be kept.
newList.add(newTmp);
}
// Replace old list with new list, which provokes two things:
// Old list will get GC'd at some point.
// New list forces that this thread has some allocations still sampled.
currentList = newList;
}
private void recursiveWrapper(int depth) {
if (depth > 0) {
recursiveWrapper(depth - 1);
return;
}
helper();
}
public void stopRun() throws InterruptedException {
jobCanStop.put(new Object());
}
public void run() {
String name = Thread.currentThread().getName();
System.err.println("Going to run: " + name);
// Wait till we are told to really start.
waitForStart();
System.err.println("Running: " + name);
for (int j = 0; j < 100; j++) {
recursiveWrapper(depth);
}
try {
// Tell the main thread we are done.
jobDone.put(new Object());
System.err.println("Waiting for main: " + name);
// Wait until the main thread says we can stop.
jobCanStop.take();
System.err.println("Waited for main: " + name);
} catch (InterruptedException e) {
failed = true;
}
}
public void waitForJobDone() {
try {
jobDone.take();
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted...");
}
}
public void waitForStart() {
try {
jobCanStart.take();
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted...");
}
}
public void start() {
try {
jobCanStart.put(new Object());
} catch(InterruptedException e) {
throw new RuntimeException("Thread got interrupted...");
}
}
}

File diff suppressed because it is too large Load Diff