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:
parent
6129ed590c
commit
89453e7c64
188
src/hotspot/share/runtime/threadHeapSampler.cpp
Normal file
188
src/hotspot/share/runtime/threadHeapSampler.cpp
Normal 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;
|
||||
}
|
74
src/hotspot/share/runtime/threadHeapSampler.hpp
Normal file
74
src/hotspot/share/runtime/threadHeapSampler.hpp
Normal 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
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
*/
|
@ -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
|
||||
*/
|
@ -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 + ")");
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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...");
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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...");
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user