# HG changeset patch # User amurillo # Date 1420748318 28800 # Node ID df4da2a16ea7b0614a26cd04590d07d0ffae5a6c # Parent 7b46afd373e1c662abf0e66edfdaaa4ef7ee9f02# Parent f43fad8786fcaf19e8381819f5e792e38c29be2c Merge diff -r 7b46afd373e1 -r df4da2a16ea7 make/hotspot_version --- a/make/hotspot_version Mon Dec 29 19:40:48 2014 -0800 +++ b/make/hotspot_version Thu Jan 08 12:18:38 2015 -0800 @@ -34,8 +34,8 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2014 HS_MAJOR_VER=25 -HS_MINOR_VER=40 -HS_BUILD_NUMBER=23 +HS_MINOR_VER=60 +HS_BUILD_NUMBER=01 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/ppc/vm/frame_ppc.cpp --- a/src/cpu/ppc/vm/frame_ppc.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/ppc/vm/frame_ppc.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -318,3 +318,10 @@ // unused... but returns fp() to minimize changes introduced by 7087445 return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) { + find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp +} +#endif diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/sparc/vm/frame_sparc.cpp --- a/src/cpu/sparc/vm/frame_sparc.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -342,7 +342,7 @@ // constructors // Construct an unpatchable, deficient frame -frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) { +void frame::init(intptr_t* sp, address pc, CodeBlob* cb) { #ifdef _LP64 assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp"); #endif @@ -364,6 +364,10 @@ #endif // ASSERT } +frame::frame(intptr_t* sp, unpatchable_t, address pc, CodeBlob* cb) { + init(sp, pc, cb); +} + frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpreted) : _sp(sp), _younger_sp(younger_sp), @@ -418,6 +422,13 @@ } } +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + init((intptr_t*)sp, (address)pc, NULL); +} +#endif + bool frame::is_interpreted_frame() const { return Interpreter::contains(pc()); } diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/sparc/vm/frame_sparc.hpp --- a/src/cpu/sparc/vm/frame_sparc.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/sparc/vm/frame_sparc.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -164,6 +164,8 @@ enum unpatchable_t { unpatchable }; frame(intptr_t* sp, unpatchable_t, address pc = NULL, CodeBlob* cb = NULL); + void init(intptr_t* sp, address pc, CodeBlob* cb); + // Walk from sp outward looking for old_sp, and return old_sp's predecessor // (i.e. return the sp from the frame where old_sp is the fp). // Register windows are assumed to be flushed for the stack in question. diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/x86/vm/frame_x86.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -717,3 +717,10 @@ assert(! is_compiled_frame(), "unknown compiled frame size"); return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + init((intptr_t*)sp, (intptr_t*)fp, (address)pc); +} +#endif diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/x86/vm/frame_x86.hpp --- a/src/cpu/x86/vm/frame_x86.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/x86/vm/frame_x86.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -187,6 +187,8 @@ frame(intptr_t* sp, intptr_t* fp); + void init(intptr_t* sp, intptr_t* fp, address pc); + // accessors for the instance variables // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; } diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/x86/vm/frame_x86.inline.hpp --- a/src/cpu/x86/vm/frame_x86.inline.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -40,7 +40,7 @@ _deopt_state = unknown; } -inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { +inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = sp; _fp = fp; @@ -58,6 +58,10 @@ } } +inline frame::frame(intptr_t* sp, intptr_t* fp, address pc) { + init(sp, fp, pc); +} + inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc) { _sp = sp; _unextended_sp = unextended_sp; diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/x86/vm/vm_version_x86.hpp --- a/src/cpu/x86/vm/vm_version_x86.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -570,10 +570,12 @@ static uint cores_per_cpu() { uint result = 1; if (is_intel()) { - if (supports_processor_topology()) { + bool supports_topology = supports_processor_topology(); + if (supports_topology) { result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus / _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus; - } else { + } + if (!supports_topology || result == 0) { result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1); } } else if (is_amd()) { diff -r 7b46afd373e1 -r df4da2a16ea7 src/cpu/zero/vm/frame_zero.cpp --- a/src/cpu/zero/vm/frame_zero.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/cpu/zero/vm/frame_zero.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -441,3 +441,10 @@ // unused... but returns fp() to minimize changes introduced by 7087445 return fp(); } + +#ifndef PRODUCT +// This is a generic constructor which is only used by pns() in debug.cpp. +frame::frame(void* sp, void* fp, void* pc) { + Unimplemented(); +} +#endif diff -r 7b46afd373e1 -r df4da2a16ea7 src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -264,7 +264,7 @@ CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(NULL, NULL, false); } else { return os::get_sender_for_C_frame(&myframe); } diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/ci/ciTypeFlow.cpp --- a/src/share/vm/ci/ciTypeFlow.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/ci/ciTypeFlow.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -36,6 +36,7 @@ #include "interpreter/bytecodes.hpp" #include "memory/allocation.inline.hpp" #include "opto/compile.hpp" +#include "opto/node.hpp" #include "runtime/deoptimization.hpp" #include "utilities/growableArray.hpp" diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/prims/unsafe.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -322,10 +322,33 @@ UNSAFE_END #ifndef SUPPORTS_NATIVE_CX8 -// Keep old code for platforms which may not have atomic jlong (8 bytes) instructions -// Volatile long versions must use locks if !VM_Version::supports_cx8(). -// support_cx8 is a surrogate for 'supports atomic long memory ops'. +// VM_Version::supports_cx8() is a surrogate for 'supports atomic long memory ops'. +// +// On platforms which do not support atomic compare-and-swap of jlong (8 byte) +// values we have to use a lock-based scheme to enforce atomicity. This has to be +// applied to all Unsafe operations that set the value of a jlong field. Even so +// the compareAndSwapLong operation will not be atomic with respect to direct stores +// to the field from Java code. It is important therefore that any Java code that +// utilizes these Unsafe jlong operations does not perform direct stores. To permit +// direct loads of the field from Java code we must also use Atomic::store within the +// locked regions. And for good measure, in case there are direct stores, we also +// employ Atomic::load within those regions. Note that the field in question must be +// volatile and so must have atomic load/store accesses applied at the Java level. +// +// The locking scheme could utilize a range of strategies for controlling the locking +// granularity: from a lock per-field through to a single global lock. The latter is +// the simplest and is used for the current implementation. Note that the Java object +// that contains the field, can not, in general, be used for locking. To do so can lead +// to deadlocks as we may introduce locking into what appears to the Java code to be a +// lock-free path. +// +// As all the locked-regions are very short and themselves non-blocking we can treat +// them as leaf routines and elide safepoint checks (ie we don't perform any thread +// state transitions even when blocking for the lock). Note that if we do choose to +// add safepoint checks and thread state transitions, we must ensure that we calculate +// the address of the field _after_ we have acquired the lock, else the object may have +// been moved by the GC UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) UnsafeWrapper("Unsafe_GetLongVolatile"); @@ -337,8 +360,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - jlong value = *addr; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong value = Atomic::load(addr); return value; } } @@ -353,8 +376,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - *addr = x; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } } UNSAFE_END @@ -463,8 +486,8 @@ else { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - ObjectLocker ol(p, THREAD); - *addr = x; + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } } #endif @@ -1213,14 +1236,19 @@ UnsafeWrapper("Unsafe_CompareAndSwapLong"); Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); +#ifdef SUPPORTS_NATIVE_CX8 + return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; +#else if (VM_Version::supports_cx8()) return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; else { jboolean success = false; - ObjectLocker ol(p, THREAD); - if (*addr == e) { *addr = x; success = true; } + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); + if (val == e) { Atomic::store(x, addr); success = true; } return success; } +#endif UNSAFE_END UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/runtime/frame.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -91,6 +91,15 @@ // Constructors frame(); +#ifndef PRODUCT + // This is a generic constructor which is only used by pns() in debug.cpp. + // pns (i.e. print native stack) uses this constructor to create a starting + // frame for stack walking. The implementation of this constructor is platform + // dependent (i.e. SPARC doesn't need an 'fp' argument an will ignore it) but + // we want to keep the signature generic because pns() is shared code. + frame(void* sp, void* fp, void* pc); +#endif + // Accessors // pc: Returns the pc at which this frame will continue normally. diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/runtime/mutexLocker.cpp --- a/src/share/vm/runtime/mutexLocker.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/runtime/mutexLocker.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -135,6 +135,10 @@ Mutex* JfrThreadGroups_lock = NULL; #endif +#ifndef SUPPORTS_NATIVE_CX8 +Mutex* UnsafeJlong_lock = NULL; +#endif + #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; static int _num_mutex; @@ -286,6 +290,9 @@ def(JfrStacktrace_lock , Mutex, special, true ); #endif +#ifndef SUPPORTS_NATIVE_CX8 + def(UnsafeJlong_lock , Mutex, special, false); +#endif } GCMutexLocker::GCMutexLocker(Monitor * mutex) { diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/runtime/mutexLocker.hpp --- a/src/share/vm/runtime/mutexLocker.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/runtime/mutexLocker.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -151,6 +151,10 @@ extern Mutex* JfrThreadGroups_lock; // protects JFR access to Thread Groups #endif +#ifndef SUPPORTS_NATIVE_CX8 +extern Mutex* UnsafeJlong_lock; // provides Unsafe atomic updates to jlongs on platforms that don't support cx8 +#endif + // A MutexLocker provides mutual exclusion with respect to a given mutex // for the scope which contains the locker. The lock is an OS lock, not // an object lock, and the two do not interoperate. Do not use Mutex-based diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/utilities/debug.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -666,6 +666,13 @@ tty->print_cr(" pm(int pc) - print Method* given compiled PC"); tty->print_cr(" findm(intptr_t pc) - finds Method*"); tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); + tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g."); + tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or"); + tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or"); + tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or"); + tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC"); + tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()"); + tty->print_cr(" - in dbx do 'frame 1' before calling pns()"); tty->print_cr("misc."); tty->print_cr(" flush() - flushes the log file"); @@ -678,3 +685,56 @@ } #endif // !PRODUCT + +void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size) { + + // see if it's a valid frame + if (fr.pc()) { + st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); + + int count = 0; + while (count++ < StackPrintLimit) { + fr.print_on_error(st, buf, buf_size); + st->cr(); + // Compiled code may use EBP register on x86 so it looks like + // non-walkable C frame. Use frame.sender() for java frames. + if (t && t->is_Java_thread()) { + // Catch very first native frame by using stack address. + // For JavaThread stack_base and stack_size should be set. + if (!t->on_local_stack((address)(fr.real_fp() + 1))) { + break; + } + if (fr.is_java_frame() || fr.is_native_frame() || fr.is_runtime_frame()) { + RegisterMap map((JavaThread*)t, false); // No update + fr = fr.sender(&map); + } else { + fr = os::get_sender_for_C_frame(&fr); + } + } else { + // is_first_C_frame() does only simple checks for frame pointer, + // it will pass if java compiled code has a pointer in EBP. + if (os::is_first_C_frame(&fr)) break; + fr = os::get_sender_for_C_frame(&fr); + } + } + + if (count > StackPrintLimit) { + st->print_cr("......"); + } + + st->cr(); + } +} + +#ifndef PRODUCT + +extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack + Command c("pns"); + static char buf[O_BUFLEN]; + Thread* t = ThreadLocalStorage::get_thread_slow(); + // Call generic frame constructor (certain arguments may be ignored) + frame fr(sp, fp, pc); + print_native_stack(tty, fr, t, buf, sizeof(buf)); +} + +#endif // !PRODUCT diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/utilities/debug.hpp --- a/src/share/vm/utilities/debug.hpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/utilities/debug.hpp Thu Jan 08 12:18:38 2015 -0800 @@ -265,4 +265,7 @@ void pd_ps(frame f); void pd_obfuscate_location(char *buf, size_t buflen); +class outputStream; +void print_native_stack(outputStream* st, frame fr, Thread* t, char* buf, int buf_size); + #endif // SHARE_VM_UTILITIES_DEBUG_HPP diff -r 7b46afd373e1 -r df4da2a16ea7 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Mon Dec 29 19:40:48 2014 -0800 +++ b/src/share/vm/utilities/vmError.cpp Thu Jan 08 12:18:38 2015 -0800 @@ -575,7 +575,7 @@ STEP(120, "(printing native stack)" ) - if (_verbose) { + if (_verbose) { if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) { // We have printed the native stack in platform-specific code // Windows/x64 needs special handling. @@ -583,43 +583,7 @@ frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); - // see if it's a valid frame - if (fr.pc()) { - st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - - - int count = 0; - while (count++ < StackPrintLimit) { - fr.print_on_error(st, buf, sizeof(buf)); - st->cr(); - // Compiled code may use EBP register on x86 so it looks like - // non-walkable C frame. Use frame.sender() for java frames. - if (_thread && _thread->is_Java_thread()) { - // Catch very first native frame by using stack address. - // For JavaThread stack_base and stack_size should be set. - if (!_thread->on_local_stack((address)(fr.sender_sp() + 1))) { - break; - } - if (fr.is_java_frame()) { - RegisterMap map((JavaThread*)_thread, false); // No update - fr = fr.sender(&map); - } else { - fr = os::get_sender_for_C_frame(&fr); - } - } else { - // is_first_C_frame() does only simple checks for frame pointer, - // it will pass if java compiled code has a pointer in EBP. - if (os::is_first_C_frame(&fr)) break; - fr = os::get_sender_for_C_frame(&fr); - } - } - - if (count > StackPrintLimit) { - st->print_cr("......"); - } - - st->cr(); - } + print_native_stack(st, fr, _thread, buf, sizeof(buf)); } } diff -r 7b46afd373e1 -r df4da2a16ea7 test/TEST.groups --- a/test/TEST.groups Mon Dec 29 19:40:48 2014 -0800 +++ b/test/TEST.groups Thu Jan 08 12:18:38 2015 -0800 @@ -171,6 +171,7 @@ gc/g1/TestShrinkAuxiliaryData20.java \ gc/g1/TestShrinkAuxiliaryData25.java \ gc/g1/TestShrinkAuxiliaryData30.java \ + gc/survivorAlignment \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ serviceability/jvmti/GetObjectSizeOverflow.java \ diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/arguments/TestSurvivorAlignmentInBytesOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.ExitCode; +import com.oracle.java.testlibrary.cli.CommandLineOptionTest; + +/** + * @test + * @bug 8031323 + * @summary Verify SurvivorAlignmentInBytes option processing. + * @library /testlibrary + * @requires vm.opt.SurvivorAlignmentInBytes == null + * & vm.opt.ObjectAlignmentInBytes == null + * & vm.opt.UnlockExperimentalVMOptions == null + * & (vm.opt.IgnoreUnrecognizedVMOptions == null + * | vm.opt.IgnoreUnrecognizedVMOptions == "false") + * @run main TestSurvivorAlignmentInBytesOption + */ +public class TestSurvivorAlignmentInBytesOption { + public static void main(String args[]) throws Throwable { + String optionName = "SurvivorAlignmentInBytes"; + String unlockExperimentalVMOpts = "UnlockExperimentalVMOptions"; + String optionIsExperimental + = CommandLineOptionTest.getExperimentalOptionErrorMessage( + optionName); + String valueIsTooSmall= ".*SurvivorAlignmentInBytes=.*must be greater" + + " than ObjectAlignmentInBytes.*"; + String mustBePowerOf2 = ".*SurvivorAlignmentInBytes=.*must be " + + "power of 2.*"; + + // Verify that without -XX:+UnlockExperimentalVMOptions usage of + // SurvivorAlignmentInBytes option will cause JVM startup failure + // with the warning message saying that that option is experimental. + CommandLineOptionTest.verifyJVMStartup( + new String[]{optionIsExperimental}, null, ExitCode.FAIL, false, + "-XX:-UnlockExperimentalVMOptions", + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, false), + CommandLineOptionTest.prepareNumericFlag(optionName, 64)); + + // Verify that with -XX:+UnlockExperimentalVMOptions passed to JVM + // usage of SurvivorAlignmentInBytes option won't cause JVM startup + // failure. + CommandLineOptionTest.verifyJVMStartup( + null, new String[]{optionIsExperimental}, ExitCode.OK, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 64)); + + // Verify that if specified SurvivorAlignmentInBytes is lower then + // ObjectAlignmentInBytes, then the JVM startup will fail with + // appropriate error message. + CommandLineOptionTest.verifyJVMStartup( + new String[]{valueIsTooSmall}, null, ExitCode.FAIL, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 2)); + + // Verify that if specified SurvivorAlignmentInBytes value is not + // a power of 2 then the JVM startup will fail with appropriate error + // message. + CommandLineOptionTest.verifyJVMStartup( + new String[]{mustBePowerOf2}, null, ExitCode.FAIL, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 127)); + + // Verify that if SurvivorAlignmentInBytes has correct value, then + // the JVM will be started without errors. + CommandLineOptionTest.verifyJVMStartup( + null, new String[]{".*SurvivorAlignmentInBytes.*"}, + ExitCode.OK, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 128)); + + // Verify that we can setup different SurvivorAlignmentInBytes values. + for (int alignment = 32; alignment <= 128; alignment *= 2) { + CommandLineOptionTest.verifyOptionValue(optionName, + Integer.toString(alignment), + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag( + optionName, alignment)); + } + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/AlignmentHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/AlignmentHelper.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.management.MemoryPoolMXBean; +import java.util.Optional; + +import sun.hotspot.WhiteBox; + +/** + * Helper class aimed to provide information about alignment of objects in + * particular heap space, expected memory usage after objects' allocation so on. + */ +public class AlignmentHelper { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static final long OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM = 8L; + + /** + * Max relative allowed actual memory usage deviation from expected memory + * usage. + */ + private static final float MAX_RELATIVE_DEVIATION = 0.05f; // 5% + + public static final long OBJECT_ALIGNMENT_IN_BYTES = Optional.ofNullable( + AlignmentHelper.WHITE_BOX.getIntxVMFlag("ObjectAlignmentInBytes")) + .orElse(AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM); + + public static final long SURVIVOR_ALIGNMENT_IN_BYTES = Optional.ofNullable( + AlignmentHelper.WHITE_BOX.getIntxVMFlag("SurvivorAlignmentInBytes")) + .orElseThrow(() ->new AssertionError( + "Unable to get SurvivorAlignmentInBytes value")); + /** + * Min amount of memory that will be occupied by an object. + */ + public static final long MIN_OBJECT_SIZE + = AlignmentHelper.WHITE_BOX.getObjectSize(new Object()); + /** + * Min amount of memory that will be occupied by an empty byte array. + */ + public static final long MIN_ARRAY_SIZE + = AlignmentHelper.WHITE_BOX.getObjectSize(new byte[0]); + + /** + * Precision at which actual memory usage in a heap space represented by + * this sizing helper could be measured. + */ + private final long memoryUsageMeasurementPrecision; + /** + * Min amount of memory that will be occupied by an object allocated in a + * heap space represented by this sizing helper. + */ + private final long minObjectSizeInThisSpace; + /** + * Object's alignment in a heap space represented by this sizing helper. + */ + private final long objectAlignmentInThisRegion; + /** + * MemoryPoolMXBean associated with a heap space represented by this sizing + * helper. + */ + private final MemoryPoolMXBean poolMXBean; + + private static long alignUp(long value, long alignment) { + return ((value - 1) / alignment + 1) * alignment; + } + + protected AlignmentHelper(long memoryUsageMeasurementPrecision, + long objectAlignmentInThisRegion, long minObjectSizeInThisSpace, + MemoryPoolMXBean poolMXBean) { + this.memoryUsageMeasurementPrecision = memoryUsageMeasurementPrecision; + this.minObjectSizeInThisSpace = minObjectSizeInThisSpace; + this.objectAlignmentInThisRegion = objectAlignmentInThisRegion; + this.poolMXBean = poolMXBean; + } + + /** + * Returns how many objects have to be allocated to fill + * {@code memoryToFill} bytes in this heap space using objects of size + * {@code objectSize}. + */ + public int getObjectsCount(long memoryToFill, long objectSize) { + return (int) (memoryToFill / getObjectSizeInThisSpace(objectSize)); + } + + /** + * Returns amount of memory that {@code objectsCount} of objects with size + * {@code objectSize} will occupy this this space after allocation. + */ + public long getExpectedMemoryUsage(long objectSize, int objectsCount) { + long correctedObjectSize = getObjectSizeInThisSpace(objectSize); + return AlignmentHelper.alignUp(correctedObjectSize * objectsCount, + memoryUsageMeasurementPrecision); + } + + /** + * Returns current memory usage in this heap space. + */ + public long getActualMemoryUsage() { + return poolMXBean.getUsage().getUsed(); + } + + /** + * Returns maximum memory usage deviation from {@code expectedMemoryUsage} + * given the max allowed relative deviation equal to + * {@code relativeDeviation}. + * + * Note that value returned by this method is aligned according to + * memory measurement precision for this heap space. + */ + public long getAllowedMemoryUsageDeviation(long expectedMemoryUsage) { + long unalignedDeviation = (long) (expectedMemoryUsage * + AlignmentHelper.MAX_RELATIVE_DEVIATION); + return AlignmentHelper.alignUp(unalignedDeviation, + memoryUsageMeasurementPrecision); + } + + /** + * Returns amount of memory that will be occupied by an object with size + * {@code objectSize} in this heap space. + */ + public long getObjectSizeInThisSpace(long objectSize) { + objectSize = Math.max(objectSize, minObjectSizeInThisSpace); + + long alignedObjectSize = AlignmentHelper.alignUp(objectSize, + objectAlignmentInThisRegion); + long sizeDiff = alignedObjectSize - objectSize; + + // If there is not enough space to fit padding object, then object will + // be aligned to {@code 2 * objectAlignmentInThisRegion}. + if (sizeDiff >= AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES + && sizeDiff < AlignmentHelper.MIN_OBJECT_SIZE) { + alignedObjectSize += AlignmentHelper.MIN_OBJECT_SIZE; + alignedObjectSize = AlignmentHelper.alignUp(alignedObjectSize, + objectAlignmentInThisRegion); + } + + return alignedObjectSize; + } + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("AlignmentHelper for memory pool '%s':%n", + poolMXBean.getName())); + builder.append(String.format("Memory usage measurement precision: %d%n", + memoryUsageMeasurementPrecision)); + builder.append(String.format("Min object size in this space: %d%n", + minObjectSizeInThisSpace)); + builder.append(String.format("Object alignment in this space: %d%n", + objectAlignmentInThisRegion)); + + return builder.toString(); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/SurvivorAlignmentTestMain.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/SurvivorAlignmentTestMain.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.util.Objects; +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.oracle.java.testlibrary.Asserts; +import com.sun.management.ThreadMXBean; +import sun.hotspot.WhiteBox; +import sun.misc.Unsafe; + +/** + * Main class for tests on {@code SurvivorAlignmentInBytes} option. + * + * Typical usage is to obtain instance using fromArgs method, allocate objects + * and verify that actual memory usage in tested heap space is close to + * expected. + */ +public class SurvivorAlignmentTestMain { + enum HeapSpace { + EDEN, + SURVIVOR, + TENURED + } + + public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + public static final long MAX_TENURING_THRESHOLD = Optional.ofNullable( + SurvivorAlignmentTestMain.WHITE_BOX.getIntxVMFlag( + "MaxTenuringThreshold")).orElse(15L); + + /** + * Regexp used to parse memory size params, like 2G, 34m or 15k. + */ + private static final Pattern SIZE_REGEX + = Pattern.compile("(?[0-9]+)(?[GMKgmk])?"); + + // Names of different heap spaces. + private static final String DEF_NEW_EDEN = "Eden Space"; + private static final String DEF_NEW_SURVIVOR = "Survivor Space"; + private static final String PAR_NEW_EDEN = "Par Eden Space"; + private static final String PAR_NEW_SURVIVOR = "Par Survivor Space"; + private static final String PS_EDEN = "PS Eden Space"; + private static final String PS_SURVIVOR = "PS Survivor Space"; + private static final String G1_EDEN = "G1 Eden Space"; + private static final String G1_SURVIVOR = "G1 Survivor Space"; + private static final String SERIAL_TENURED = "Tenured Gen"; + private static final String CMS_TENURED = "CMS Old Gen"; + private static final String PS_TENURED = "PS Old Gen"; + private static final String G1_TENURED = "G1 Old Gen"; + + private static final long G1_HEAP_REGION_SIZE = Optional.ofNullable( + SurvivorAlignmentTestMain.WHITE_BOX.getUintxVMFlag( + "G1HeapRegionSize")).orElse(-1L); + + /** + * Min size of free chunk in CMS generation. + * An object allocated in CMS generation will at least occupy this amount + * of bytes. + */ + private static final long CMS_MIN_FREE_CHUNK_SIZE + = 3L * Unsafe.ADDRESS_SIZE; + + private static final AlignmentHelper EDEN_SPACE_HELPER; + private static final AlignmentHelper SURVIVOR_SPACE_HELPER; + private static final AlignmentHelper TENURED_SPACE_HELPER; + /** + * Amount of memory that should be filled during a test run. + */ + private final long memoryToFill; + /** + * The size of an objects that will be allocated during a test run. + */ + private final long objectSize; + /** + * Amount of memory that will be actually occupied by an object in eden + * space. + */ + private final long actualObjectSize; + /** + * Storage for allocated objects. + */ + private final Object[] garbage; + /** + * Heap space whose memory usage is a subject of assertions during the test + * run. + */ + private final HeapSpace testedSpace; + + private long[] baselinedThreadMemoryUsage = null; + private long[] threadIds = null; + + /** + * Initialize {@code EDEN_SPACE_HELPER}, {@code SURVIVOR_SPACE_HELPER} and + * {@code TENURED_SPACE_HELPER} to represent heap spaces in use. + * + * Note that regardless to GC object's alignment in survivor space is + * expected to be equal to {@code SurvivorAlignmentInBytes} value and + * alignment in other spaces is expected to be equal to + * {@code ObjectAlignmentInBytes} value. + * + * In CMS generation we can't allocate less then {@code MinFreeChunk} value, + * for other CGs we expect that object of size {@code MIN_OBJECT_SIZE} + * could be allocated as it is (of course, its size could be aligned + * according to alignment value used in a particular space). + * + * For G1 GC MXBeans could report memory usage only with region size + * precision (if an object allocated in some G1 heap region, then all region + * will claimed as used), so for G1's spaces precision is equal to + * {@code G1HeapRegionSize} value. + */ + static { + AlignmentHelper edenHelper = null; + AlignmentHelper survivorHelper = null; + AlignmentHelper tenuredHelper = null; + for (MemoryPoolMXBean pool : ManagementFactory.getMemoryPoolMXBeans()) { + switch (pool.getName()) { + case SurvivorAlignmentTestMain.DEF_NEW_EDEN: + case SurvivorAlignmentTestMain.PAR_NEW_EDEN: + case SurvivorAlignmentTestMain.PS_EDEN: + Asserts.assertNull(edenHelper, + "Only one bean for eden space is expected."); + edenHelper = new AlignmentHelper( + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.MIN_OBJECT_SIZE, pool); + break; + case SurvivorAlignmentTestMain.G1_EDEN: + Asserts.assertNull(edenHelper, + "Only one bean for eden space is expected."); + edenHelper = new AlignmentHelper( + SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE, + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.MIN_OBJECT_SIZE, pool); + break; + case SurvivorAlignmentTestMain.DEF_NEW_SURVIVOR: + case SurvivorAlignmentTestMain.PAR_NEW_SURVIVOR: + case SurvivorAlignmentTestMain.PS_SURVIVOR: + Asserts.assertNull(survivorHelper, + "Only one bean for survivor space is expected."); + survivorHelper = new AlignmentHelper( + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES, + AlignmentHelper.MIN_OBJECT_SIZE, pool); + break; + case SurvivorAlignmentTestMain.G1_SURVIVOR: + Asserts.assertNull(survivorHelper, + "Only one bean for survivor space is expected."); + survivorHelper = new AlignmentHelper( + SurvivorAlignmentTestMain.G1_HEAP_REGION_SIZE, + AlignmentHelper.SURVIVOR_ALIGNMENT_IN_BYTES, + AlignmentHelper.MIN_OBJECT_SIZE, pool); + break; + case SurvivorAlignmentTestMain.SERIAL_TENURED: + case SurvivorAlignmentTestMain.PS_TENURED: + case SurvivorAlignmentTestMain.G1_TENURED: + Asserts.assertNull(tenuredHelper, + "Only one bean for tenured space is expected."); + tenuredHelper = new AlignmentHelper( + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.MIN_OBJECT_SIZE, pool); + break; + case SurvivorAlignmentTestMain.CMS_TENURED: + Asserts.assertNull(tenuredHelper, + "Only one bean for tenured space is expected."); + tenuredHelper = new AlignmentHelper( + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES, + SurvivorAlignmentTestMain.CMS_MIN_FREE_CHUNK_SIZE, + pool); + break; + } + } + EDEN_SPACE_HELPER = Objects.requireNonNull(edenHelper, + "AlignmentHelper for eden space should be initialized."); + SURVIVOR_SPACE_HELPER = Objects.requireNonNull(survivorHelper, + "AlignmentHelper for survivor space should be initialized."); + TENURED_SPACE_HELPER = Objects.requireNonNull(tenuredHelper, + "AlignmentHelper for tenured space should be initialized."); + } + /** + * Returns an SurvivorAlignmentTestMain instance constructed using CLI + * options. + * + * Following options are expected: + *
    + *
  • memoryToFill
  • + *
  • objectSize
  • + *
+ * + * Both argument may contain multiplier suffix k, m or g. + */ + public static SurvivorAlignmentTestMain fromArgs(String[] args) { + Asserts.assertEQ(args.length, 3, "Expected three arguments: " + + "memory size, object size and tested heap space name."); + + long memoryToFill = parseSize(args[0]); + long objectSize = Math.max(parseSize(args[1]), + AlignmentHelper.MIN_ARRAY_SIZE); + HeapSpace testedSpace = HeapSpace.valueOf(args[2]); + + return new SurvivorAlignmentTestMain(memoryToFill, objectSize, + testedSpace); + } + + /** + * Returns a value parsed from a string with format + * <integer><multiplier>. + */ + private static long parseSize(String sizeString) { + Matcher matcher = SIZE_REGEX.matcher(sizeString); + Asserts.assertTrue(matcher.matches(), + "sizeString should have following format \"[0-9]+([MBK])?\""); + long size = Long.valueOf(matcher.group("size")); + + if (matcher.group("multiplier") != null) { + long K = 1024L; + // fall through multipliers + switch (matcher.group("multiplier").toLowerCase()) { + case "g": + size *= K; + case "m": + size *= K; + case "k": + size *= K; + } + } + return size; + } + + private SurvivorAlignmentTestMain(long memoryToFill, long objectSize, + HeapSpace testedSpace) { + this.objectSize = objectSize; + this.memoryToFill = memoryToFill; + this.testedSpace = testedSpace; + + AlignmentHelper helper = SurvivorAlignmentTestMain.EDEN_SPACE_HELPER; + + this.actualObjectSize = helper.getObjectSizeInThisSpace( + this.objectSize); + int arrayLength = helper.getObjectsCount(memoryToFill, this.objectSize); + garbage = new Object[arrayLength]; + } + + /** + * Allocate byte arrays to fill {@code memoryToFill} memory. + */ + public void allocate() { + int byteArrayLength = Math.max((int) (objectSize + - Unsafe.ARRAY_BYTE_BASE_OFFSET), 0); + + for (int i = 0; i < garbage.length; i++) { + garbage[i] = new byte[byteArrayLength]; + } + } + + /** + * Release memory occupied after {@code allocate} call. + */ + public void release() { + for (int i = 0; i < garbage.length; i++) { + garbage[i] = null; + } + } + + /** + * Returns expected amount of memory occupied in a {@code heapSpace} by + * objects referenced from {@code garbage} array. + */ + public long getExpectedMemoryUsage() { + AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace); + return alignmentHelper.getExpectedMemoryUsage(objectSize, + garbage.length); + } + + /** + * Verifies that memory usage in a {@code heapSpace} deviates from + * {@code expectedUsage} for no more than {@code MAX_RELATIVE_DEVIATION}. + */ + public void verifyMemoryUsage(long expectedUsage) { + AlignmentHelper alignmentHelper = getAlignmentHelper(testedSpace); + + long actualMemoryUsage = alignmentHelper.getActualMemoryUsage(); + boolean otherThreadsAllocatedMemory = areOtherThreadsAllocatedMemory(); + + long memoryUsageDiff = Math.abs(actualMemoryUsage - expectedUsage); + long maxAllowedUsageDiff + = alignmentHelper.getAllowedMemoryUsageDeviation(expectedUsage); + + System.out.println("Verifying memory usage in space: " + testedSpace); + System.out.println("Allocated objects count: " + garbage.length); + System.out.println("Desired object size: " + objectSize); + System.out.println("Actual object size: " + actualObjectSize); + System.out.println("Expected object size in space: " + + alignmentHelper.getObjectSizeInThisSpace(objectSize)); + System.out.println("Expected memory usage: " + expectedUsage); + System.out.println("Actual memory usage: " + actualMemoryUsage); + System.out.println("Memory usage diff: " + memoryUsageDiff); + System.out.println("Max allowed usage diff: " + maxAllowedUsageDiff); + + if (memoryUsageDiff > maxAllowedUsageDiff + && otherThreadsAllocatedMemory) { + System.out.println("Memory usage diff is incorrect, but it seems " + + "like someone else allocated objects"); + return; + } + + Asserts.assertLTE(memoryUsageDiff, maxAllowedUsageDiff, + "Actual memory usage should not deviate from expected for " + + "more then " + maxAllowedUsageDiff); + } + + /** + * Baselines amount of memory allocated by each thread. + */ + public void baselineMemoryAllocation() { + ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); + threadIds = bean.getAllThreadIds(); + baselinedThreadMemoryUsage = bean.getThreadAllocatedBytes(threadIds); + } + + /** + * Checks if threads other then the current thread were allocating objects + * after baselinedThreadMemoryUsage call. + * + * If baselinedThreadMemoryUsage was not called, then this method will return + * {@code false}. + */ + public boolean areOtherThreadsAllocatedMemory() { + if (baselinedThreadMemoryUsage == null) { + return false; + } + + ThreadMXBean bean = (ThreadMXBean) ManagementFactory.getThreadMXBean(); + long currentMemoryAllocation[] + = bean.getThreadAllocatedBytes(threadIds); + boolean otherThreadsAllocatedMemory = false; + + System.out.println("Verifying amount of memory allocated by threads:"); + for (int i = 0; i < threadIds.length; i++) { + System.out.format("Thread %d%nbaseline allocation: %d" + + "%ncurrent allocation:%d%n", threadIds[i], + baselinedThreadMemoryUsage[i], currentMemoryAllocation[i]); + System.out.println(bean.getThreadInfo(threadIds[i])); + + long bytesAllocated = Math.abs(currentMemoryAllocation[i] + - baselinedThreadMemoryUsage[i]); + if (bytesAllocated > 0 + && threadIds[i] != Thread.currentThread().getId()) { + otherThreadsAllocatedMemory = true; + } + } + + return otherThreadsAllocatedMemory; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append(String.format("SurvivorAlignmentTestMain info:%n")); + builder.append(String.format("Desired object size: %d%n", objectSize)); + builder.append(String.format("Memory to fill: %d%n", memoryToFill)); + builder.append(String.format("Objects to be allocated: %d%n", + garbage.length)); + + builder.append(String.format("Alignment helpers to be used: %n")); + for (HeapSpace heapSpace: HeapSpace.values()) { + builder.append(String.format("For space %s:%n%s%n", heapSpace, + getAlignmentHelper(heapSpace))); + } + + return builder.toString(); + } + + /** + * Returns {@code AlignmentHelper} for a space {@code heapSpace}. + */ + public static AlignmentHelper getAlignmentHelper(HeapSpace heapSpace) { + switch (heapSpace) { + case EDEN: + return SurvivorAlignmentTestMain.EDEN_SPACE_HELPER; + case SURVIVOR: + return SurvivorAlignmentTestMain.SURVIVOR_SPACE_HELPER; + case TENURED: + return SurvivorAlignmentTestMain.TENURED_SPACE_HELPER; + default: + throw new Error("Unexpected heap space: " + heapSpace); + } + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/TestAllocationInEden.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/TestAllocationInEden.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031323 + * @summary Verify that object's alignment in eden space is not affected by + * SurvivorAlignmentInBytes option. + * @library /testlibrary /testlibrary/whitebox + * @build TestAllocationInEden SurvivorAlignmentTestMain AlignmentHelper + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 9 EDEN + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 47 EDEN + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 9 EDEN + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 87 EDEN + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 9 EDEN + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent + * TestAllocationInEden 10m 147 EDEN + */ +public class TestAllocationInEden { + public static void main(String args[]) { + SurvivorAlignmentTestMain test + = SurvivorAlignmentTestMain.fromArgs(args); + System.out.println(test); + + long expectedMemoryUsage = test.getExpectedMemoryUsage(); + test.baselineMemoryAllocation(); + System.gc(); + + test.allocate(); + + test.verifyMemoryUsage(expectedMemoryUsage); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031323 + * @summary Verify that objects promoted from eden space to tenured space during + * full GC are not aligned to SurvivorAlignmentInBytes value. + * @library /testlibrary /testlibrary/whitebox + * @build TestPromotionFromEdenToTenured SurvivorAlignmentTestMain + * AlignmentHelper + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromEdenToTenured 10m 9 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromEdenToTenured 10m 47 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32m -XX:MaxHeapSize=96m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromEdenToTenured 10m 9 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32m -XX:MaxHeapSize=128m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromEdenToTenured 10m 87 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32M -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromEdenToTenured 10m 9 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromEdenToTenured 10m 147 TENURED + */ +public class TestPromotionFromEdenToTenured { + public static void main(String args[]) { + SurvivorAlignmentTestMain test + = SurvivorAlignmentTestMain.fromArgs(args); + System.out.println(test); + + long expectedMemoryUsage = test.getExpectedMemoryUsage(); + test.baselineMemoryAllocation(); + System.gc(); + // increase expected usage by current old gen usage + expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( + SurvivorAlignmentTestMain.HeapSpace.TENURED) + .getActualMemoryUsage(); + + test.allocate(); + System.gc(); + + test.verifyMemoryUsage(expectedMemoryUsage); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031323 + * @summary Verify that objects promoted from survivor space to tenured space + * during full GC are not aligned to SurvivorAlignmentInBytes value. + * @library /testlibrary /testlibrary/whitebox + * @build TestPromotionFromSurvivorToTenuredAfterFullGC + * SurvivorAlignmentTestMain AlignmentHelper + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 47 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m + * -XX:OldSize=32m -XX:MaxHeapSize=232m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 87 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m + * -XX:OldSize=32M -XX:MaxHeapSize=288m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 147 + * TENURED + */ +public class TestPromotionFromSurvivorToTenuredAfterFullGC { + public static void main(String args[]) { + SurvivorAlignmentTestMain test + = SurvivorAlignmentTestMain.fromArgs(args); + System.out.println(test); + + long expectedMemoryUsage = test.getExpectedMemoryUsage(); + test.baselineMemoryAllocation(); + System.gc(); + // increase expected usage by current old gen usage + expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( + SurvivorAlignmentTestMain.HeapSpace.TENURED) + .getActualMemoryUsage(); + + test.allocate(); + SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); + System.gc(); + + test.verifyMemoryUsage(expectedMemoryUsage); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031323 + * @summary Verify that objects promoted from survivor space to tenured space + * when their age exceeded tenuring threshold are not aligned to + * SurvivorAlignmentInBytes value. + * @library /testlibrary /testlibrary/whitebox + * @build TestPromotionFromSurvivorToTenuredAfterMinorGC + * SurvivorAlignmentTestMain AlignmentHelper + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 47 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m + * -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 87 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m + * -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 + * TENURED + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent + * -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 + * TestPromotionFromSurvivorToTenuredAfterMinorGC 20m 147 + * TENURED + */ +public class TestPromotionFromSurvivorToTenuredAfterMinorGC { + public static void main(String args[]) throws Exception { + SurvivorAlignmentTestMain test + = SurvivorAlignmentTestMain.fromArgs(args); + System.out.println(test); + + long expectedMemoryUsage = test.getExpectedMemoryUsage(); + test.baselineMemoryAllocation(); + SurvivorAlignmentTestMain.WHITE_BOX.fullGC(); + // increase expected usage by current old gen usage + expectedMemoryUsage += SurvivorAlignmentTestMain.getAlignmentHelper( + SurvivorAlignmentTestMain.HeapSpace.TENURED) + .getActualMemoryUsage(); + + test.allocate(); + for (int i = 0; i <= SurvivorAlignmentTestMain.MAX_TENURING_THRESHOLD; + i++) { + SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); + } + + test.verifyMemoryUsage(expectedMemoryUsage); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/gc/survivorAlignment/TestPromotionToSurvivor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/survivorAlignment/TestPromotionToSurvivor.java Thu Jan 08 12:18:38 2015 -0800 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8031323 + * @summary Verify that objects promoted from eden space to survivor space after + * minor GC are aligned to SurvivorAlignmentInBytes. + * @library /testlibrary /testlibrary/whitebox + * @build TestPromotionToSurvivor + * SurvivorAlignmentTestMain AlignmentHelper + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 10m 9 SURVIVOR + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 20m 47 SURVIVOR + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 8m 9 SURVIVOR + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 20m 87 SURVIVOR + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m + * -XX:MaxHeapSize=384m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 10m 9 SURVIVOR + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m + * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions + * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent + * TestPromotionToSurvivor 20m 147 SURVIVOR + */ +public class TestPromotionToSurvivor { + public static void main(String args[]) { + SurvivorAlignmentTestMain test + = SurvivorAlignmentTestMain.fromArgs(args); + System.out.println(test); + + long expectedUsage = test.getExpectedMemoryUsage(); + test.baselineMemoryAllocation(); + SurvivorAlignmentTestMain.WHITE_BOX.fullGC(); + + test.allocate(); + SurvivorAlignmentTestMain.WHITE_BOX.youngGC(); + + test.verifyMemoryUsage(expectedUsage); + } +} diff -r 7b46afd373e1 -r df4da2a16ea7 test/serviceability/sa/jmap-hashcode/Test8028623.java --- a/test/serviceability/sa/jmap-hashcode/Test8028623.java Mon Dec 29 19:40:48 2014 -0800 +++ b/test/serviceability/sa/jmap-hashcode/Test8028623.java Thu Jan 08 12:18:38 2015 -0800 @@ -33,20 +33,25 @@ import com.oracle.java.testlibrary.JDKToolLauncher; import com.oracle.java.testlibrary.OutputBuffer; +import com.oracle.java.testlibrary.Platform; import com.oracle.java.testlibrary.ProcessTools; import java.io.File; public class Test8028623 { - public static int à = 1; + public static int \u00CB = 1; public static String dumpFile = "heap.out"; public static void main (String[] args) { - System.out.println(Ã); + System.out.println(\u00CB); try { + if (!Platform.shouldSAAttach()) { + System.out.println("SA attach not expected to work - test skipped."); + return; + } int pid = ProcessTools.getProcessId(); JDKToolLauncher jmap = JDKToolLauncher.create("jmap") .addToolArg("-F") diff -r 7b46afd373e1 -r df4da2a16ea7 test/testlibrary/com/oracle/java/testlibrary/Platform.java --- a/test/testlibrary/com/oracle/java/testlibrary/Platform.java Mon Dec 29 19:40:48 2014 -0800 +++ b/test/testlibrary/com/oracle/java/testlibrary/Platform.java Thu Jan 08 12:18:38 2015 -0800 @@ -23,12 +23,15 @@ package com.oracle.java.testlibrary; +import com.oracle.java.testlibrary.Utils; + public class Platform { private static final String osName = System.getProperty("os.name"); private static final String dataModel = System.getProperty("sun.arch.data.model"); private static final String vmVersion = System.getProperty("java.vm.version"); private static final String osArch = System.getProperty("os.arch"); private static final String vmName = System.getProperty("java.vm.name"); + private static final String userName = System.getProperty("user.name"); public static boolean isClient() { return vmName.endsWith(" Client VM"); @@ -121,4 +124,56 @@ return osArch; } + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. + */ + public static boolean shouldSAAttach() throws Exception { + + if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". Then expect permission to attach + * if we are root, so return true. Then return false for an expected denial + * if "ptrace_scope" is 1, and true otherwise. + */ + public static boolean canPtraceAttachLinux() throws Exception { + + // SELinux deny_ptrace: + String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace"); + if (deny_ptrace != null && deny_ptrace.contains("1")) { + // ptrace will be denied: + return false; + } + + if (userName.equals("root")) { + return true; + } + + // ptrace_scope: + String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope"); + if (ptrace_scope != null && ptrace_scope.contains("1")) { + // ptrace will be denied: + return false; + } + + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + public static boolean canAttachOSX() throws Exception { + return userName.equals("root"); + } } diff -r 7b46afd373e1 -r df4da2a16ea7 test/testlibrary/com/oracle/java/testlibrary/Utils.java --- a/test/testlibrary/com/oracle/java/testlibrary/Utils.java Mon Dec 29 19:40:48 2014 -0800 +++ b/test/testlibrary/com/oracle/java/testlibrary/Utils.java Thu Jan 08 12:18:38 2015 -0800 @@ -299,6 +299,35 @@ } /** + * Return the contents of the named file as a single String, + * or null if not found. + * @param filename name of the file to read + * @return String contents of file, or null if file not found. + */ + public static String fileAsString(String filename) { + StringBuilder result = new StringBuilder(); + try { + File file = new File(filename); + if (file.exists()) { + BufferedReader reader = new BufferedReader(new FileReader(file)); + while (true) { + String line = reader.readLine(); + if (line == null) { + break; + } + result.append(line).append("\n"); + } + } else { + // Does not exist: + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } + return result.toString(); + } + + /** * @return Unsafe instance. */ public static synchronized Unsafe getUnsafe() {