mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-04 21:20:17 +00:00
Merge
This commit is contained in:
commit
8957d8798f
@ -176,6 +176,9 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_ProcessHandleImpl_00024Info_info0;
|
||||
Java_java_lang_ProcessImpl_init;
|
||||
Java_java_lang_ProcessImpl_forkAndExec;
|
||||
Java_java_lang_ref_Reference_getAndClearReferencePendingList;
|
||||
Java_java_lang_ref_Reference_hasReferencePendingList;
|
||||
Java_java_lang_ref_Reference_waitForReferencePendingList;
|
||||
Java_java_lang_reflect_Array_get;
|
||||
Java_java_lang_reflect_Array_getBoolean;
|
||||
Java_java_lang_reflect_Array_getByte;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2016, 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
|
||||
@ -110,22 +110,6 @@ public abstract class Reference<T> {
|
||||
private transient Reference<T> discovered; /* used by VM */
|
||||
|
||||
|
||||
/* Object used to synchronize with the garbage collector. The collector
|
||||
* must acquire this lock at the beginning of each collection cycle. It is
|
||||
* therefore critical that any code holding this lock complete as quickly
|
||||
* as possible, allocate no new objects, and avoid calling user code.
|
||||
*/
|
||||
private static class Lock { }
|
||||
private static Lock lock = new Lock();
|
||||
|
||||
|
||||
/* List of References waiting to be enqueued. The collector adds
|
||||
* References to this list, while the Reference-handler thread removes
|
||||
* them. This list is protected by the above lock object. The
|
||||
* list uses the discovered field to link its elements.
|
||||
*/
|
||||
private static Reference<Object> pending = null;
|
||||
|
||||
/* High-priority thread to enqueue pending References
|
||||
*/
|
||||
private static class ReferenceHandler extends Thread {
|
||||
@ -139,10 +123,9 @@ public abstract class Reference<T> {
|
||||
}
|
||||
|
||||
static {
|
||||
// pre-load and initialize InterruptedException and Cleaner classes
|
||||
// so that we don't get into trouble later in the run loop if there's
|
||||
// memory shortage while loading/initializing them lazily.
|
||||
ensureClassInitialized(InterruptedException.class);
|
||||
// pre-load and initialize Cleaner class so that we don't
|
||||
// get into trouble later in the run loop if there's
|
||||
// memory shortage while loading/initializing it lazily.
|
||||
ensureClassInitialized(Cleaner.class);
|
||||
}
|
||||
|
||||
@ -152,72 +135,80 @@ public abstract class Reference<T> {
|
||||
|
||||
public void run() {
|
||||
while (true) {
|
||||
tryHandlePending(true);
|
||||
processPendingReferences();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try handle pending {@link Reference} if there is one.<p>
|
||||
* Return {@code true} as a hint that there might be another
|
||||
* {@link Reference} pending or {@code false} when there are no more pending
|
||||
* {@link Reference}s at the moment and the program can do some other
|
||||
* useful work instead of looping.
|
||||
*
|
||||
* @param waitForNotify if {@code true} and there was no pending
|
||||
* {@link Reference}, wait until notified from VM
|
||||
* or interrupted; if {@code false}, return immediately
|
||||
* when there is no pending {@link Reference}.
|
||||
* @return {@code true} if there was a {@link Reference} pending and it
|
||||
* was processed, or we waited for notification and either got it
|
||||
* or thread was interrupted before being notified;
|
||||
* {@code false} otherwise.
|
||||
/* Atomically get and clear (set to null) the VM's pending list.
|
||||
*/
|
||||
static boolean tryHandlePending(boolean waitForNotify) {
|
||||
Reference<Object> r;
|
||||
Cleaner c;
|
||||
try {
|
||||
synchronized (lock) {
|
||||
if (pending != null) {
|
||||
r = pending;
|
||||
// 'instanceof' might throw OutOfMemoryError sometimes
|
||||
// so do this before un-linking 'r' from the 'pending' chain...
|
||||
c = r instanceof Cleaner ? (Cleaner) r : null;
|
||||
// unlink 'r' from 'pending' chain
|
||||
pending = r.discovered;
|
||||
r.discovered = null;
|
||||
} else {
|
||||
// The waiting on the lock may cause an OutOfMemoryError
|
||||
// because it may try to allocate exception objects.
|
||||
if (waitForNotify) {
|
||||
lock.wait();
|
||||
}
|
||||
// retry if waited
|
||||
return waitForNotify;
|
||||
private static native Reference<Object> getAndClearReferencePendingList();
|
||||
|
||||
/* Test whether the VM's pending list contains any entries.
|
||||
*/
|
||||
private static native boolean hasReferencePendingList();
|
||||
|
||||
/* Wait until the VM's pending list may be non-null.
|
||||
*/
|
||||
private static native void waitForReferencePendingList();
|
||||
|
||||
private static final Object processPendingLock = new Object();
|
||||
private static boolean processPendingActive = false;
|
||||
|
||||
private static void processPendingReferences() {
|
||||
// Only the singleton reference processing thread calls
|
||||
// waitForReferencePendingList() and getAndClearReferencePendingList().
|
||||
// These are separate operations to avoid a race with other threads
|
||||
// that are calling waitForReferenceProcessing().
|
||||
waitForReferencePendingList();
|
||||
Reference<Object> pendingList;
|
||||
synchronized (processPendingLock) {
|
||||
pendingList = getAndClearReferencePendingList();
|
||||
processPendingActive = true;
|
||||
}
|
||||
while (pendingList != null) {
|
||||
Reference<Object> ref = pendingList;
|
||||
pendingList = ref.discovered;
|
||||
ref.discovered = null;
|
||||
|
||||
if (ref instanceof Cleaner) {
|
||||
((Cleaner)ref).clean();
|
||||
// Notify any waiters that progress has been made.
|
||||
// This improves latency for nio.Bits waiters, which
|
||||
// are the only important ones.
|
||||
synchronized (processPendingLock) {
|
||||
processPendingLock.notifyAll();
|
||||
}
|
||||
} else {
|
||||
ReferenceQueue<? super Object> q = ref.queue;
|
||||
if (q != ReferenceQueue.NULL) q.enqueue(ref);
|
||||
}
|
||||
} catch (OutOfMemoryError x) {
|
||||
// Give other threads CPU time so they hopefully drop some live references
|
||||
// and GC reclaims some space.
|
||||
// Also prevent CPU intensive spinning in case 'r instanceof Cleaner' above
|
||||
// persistently throws OOME for some time...
|
||||
Thread.yield();
|
||||
// retry
|
||||
return true;
|
||||
} catch (InterruptedException x) {
|
||||
// retry
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fast path for cleaners
|
||||
if (c != null) {
|
||||
c.clean();
|
||||
return true;
|
||||
// Notify any waiters of completion of current round.
|
||||
synchronized (processPendingLock) {
|
||||
processPendingActive = false;
|
||||
processPendingLock.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceQueue<? super Object> q = r.queue;
|
||||
if (q != ReferenceQueue.NULL) q.enqueue(r);
|
||||
return true;
|
||||
// Wait for progress in reference processing.
|
||||
//
|
||||
// Returns true after waiting (for notification from the reference
|
||||
// processing thread) if either (1) the VM has any pending
|
||||
// references, or (2) the reference processing thread is
|
||||
// processing references. Otherwise, returns false immediately.
|
||||
private static boolean waitForReferenceProcessing()
|
||||
throws InterruptedException
|
||||
{
|
||||
synchronized (processPendingLock) {
|
||||
if (processPendingActive || hasReferencePendingList()) {
|
||||
// Wait for progress, not necessarily completion.
|
||||
processPendingLock.wait();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
@ -236,8 +227,10 @@ public abstract class Reference<T> {
|
||||
// provide access in SharedSecrets
|
||||
SharedSecrets.setJavaLangRefAccess(new JavaLangRefAccess() {
|
||||
@Override
|
||||
public boolean tryHandlePendingReference() {
|
||||
return tryHandlePending(false);
|
||||
public boolean waitForReferenceProcessing()
|
||||
throws InterruptedException
|
||||
{
|
||||
return Reference.waitForReferenceProcessing();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -131,23 +131,38 @@ class Bits { // package-private
|
||||
}
|
||||
|
||||
final JavaLangRefAccess jlra = SharedSecrets.getJavaLangRefAccess();
|
||||
|
||||
// retry while helping enqueue pending Reference objects
|
||||
// which includes executing pending Cleaner(s) which includes
|
||||
// Cleaner(s) that free direct buffer memory
|
||||
while (jlra.tryHandlePendingReference()) {
|
||||
if (tryReserveMemory(size, cap)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// trigger VM's Reference processing
|
||||
System.gc();
|
||||
|
||||
// a retry loop with exponential back-off delays
|
||||
// (this gives VM some time to do it's job)
|
||||
boolean interrupted = false;
|
||||
try {
|
||||
|
||||
// Retry allocation until success or there are no more
|
||||
// references (including Cleaners that might free direct
|
||||
// buffer memory) to process and allocation still fails.
|
||||
boolean refprocActive;
|
||||
do {
|
||||
try {
|
||||
refprocActive = jlra.waitForReferenceProcessing();
|
||||
} catch (InterruptedException e) {
|
||||
// Defer interrupts and keep trying.
|
||||
interrupted = true;
|
||||
refprocActive = true;
|
||||
}
|
||||
if (tryReserveMemory(size, cap)) {
|
||||
return;
|
||||
}
|
||||
} while (refprocActive);
|
||||
|
||||
// trigger VM's Reference processing
|
||||
System.gc();
|
||||
|
||||
// A retry loop with exponential back-off delays.
|
||||
// Sometimes it would suffice to give up once reference
|
||||
// processing is complete. But if there are many threads
|
||||
// competing for memory, this gives more opportunities for
|
||||
// any given thread to make progress. In particular, this
|
||||
// seems to be enough for a stress test like
|
||||
// DirectBufferAllocTest to (usually) succeed, while
|
||||
// without it that test likely fails. Since failure here
|
||||
// ends in OOME, there's no need to hurry.
|
||||
long sleepTime = 1;
|
||||
int sleeps = 0;
|
||||
while (true) {
|
||||
@ -157,14 +172,14 @@ class Bits { // package-private
|
||||
if (sleeps >= MAX_SLEEPS) {
|
||||
break;
|
||||
}
|
||||
if (!jlra.tryHandlePendingReference()) {
|
||||
try {
|
||||
try {
|
||||
if (!jlra.waitForReferenceProcessing()) {
|
||||
Thread.sleep(sleepTime);
|
||||
sleepTime <<= 1;
|
||||
sleeps++;
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
interrupted = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, 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
|
||||
@ -28,12 +28,12 @@ package jdk.internal.misc;
|
||||
public interface JavaLangRefAccess {
|
||||
|
||||
/**
|
||||
* Help ReferenceHandler thread process next pending
|
||||
* {@link java.lang.ref.Reference}
|
||||
* Wait for progress in {@link java.lang.ref.Reference}
|
||||
* processing. If there aren't any pending {@link
|
||||
* java.lang.ref.Reference}s, return immediately.
|
||||
*
|
||||
* @return {@code true} if there was a pending reference and it
|
||||
* was enqueue-ed or {@code false} if there was no
|
||||
* pending reference
|
||||
* @return {@code true} if there were any pending
|
||||
* {@link java.lang.ref.Reference}s, {@code false} otherwise.
|
||||
*/
|
||||
boolean tryHandlePendingReference();
|
||||
boolean waitForReferenceProcessing() throws InterruptedException;
|
||||
}
|
||||
|
||||
@ -1197,6 +1197,9 @@ public final class Unsafe {
|
||||
if (hostClass == null || data == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (hostClass.isArray() || hostClass.isPrimitive()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
return defineAnonymousClass0(hostClass, data, cpPatches);
|
||||
}
|
||||
|
||||
@ -281,6 +281,18 @@ JVM_GetSystemPackage(JNIEnv *env, jstring name);
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
JVM_GetSystemPackages(JNIEnv *env);
|
||||
|
||||
/*
|
||||
* java.lang.ref.Reference
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL
|
||||
JVM_GetAndClearReferencePendingList(JNIEnv *env);
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
JVM_HasReferencePendingList(JNIEnv *env);
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
JVM_WaitForReferencePendingList(JNIEnv *env);
|
||||
|
||||
/*
|
||||
* java.io.ObjectInputStream
|
||||
*/
|
||||
|
||||
45
jdk/src/java.base/share/native/libjava/Reference.c
Normal file
45
jdk/src/java.base/share/native/libjava/Reference.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 "jvm.h"
|
||||
#include "java_lang_ref_Reference.h"
|
||||
|
||||
JNIEXPORT jobject JNICALL
|
||||
Java_java_lang_ref_Reference_getAndClearReferencePendingList(JNIEnv *env, jclass ignore)
|
||||
{
|
||||
return JVM_GetAndClearReferencePendingList(env);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_java_lang_ref_Reference_hasReferencePendingList(JNIEnv *env, jclass ignore)
|
||||
{
|
||||
return JVM_HasReferencePendingList(env);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_lang_ref_Reference_waitForReferencePendingList(JNIEnv *env, jclass ignore)
|
||||
{
|
||||
JVM_WaitForReferencePendingList(env);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2016, 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
|
||||
@ -1707,25 +1707,6 @@ public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException,
|
||||
OperationsException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ObjectInputStream deserialize(String className, byte[] data) throws OperationsException,
|
||||
ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public ObjectInputStream deserialize(String className, ObjectName loaderName,
|
||||
byte[] data) throws InstanceNotFoundException, OperationsException,
|
||||
ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
public ClassLoaderRepository getClassLoaderRepository() {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2016, 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
|
||||
@ -94,32 +94,6 @@ public interface MBeanServerInterceptor extends MBeanServer {
|
||||
throws ReflectionException, MBeanException,
|
||||
InstanceNotFoundException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(ObjectName name, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className, byte[] data)
|
||||
throws OperationsException, ReflectionException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually hrows UnsupportedOperationException.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className,
|
||||
ObjectName loaderName, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException,
|
||||
ReflectionException;
|
||||
|
||||
/**
|
||||
* This method should never be called.
|
||||
* Usually throws UnsupportedOperationException.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2016, 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
|
||||
@ -655,6 +655,8 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* used for the de-serialization.
|
||||
* @param data The byte array to be de-sererialized.
|
||||
*
|
||||
* @implSpec This method throws {@link UnsupportedOperationException} by default.
|
||||
*
|
||||
* @return The de-serialized object stream.
|
||||
*
|
||||
* @exception InstanceNotFoundException The MBean specified is not
|
||||
@ -665,10 +667,11 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* @deprecated Use {@link #getClassLoaderFor getClassLoaderFor} to
|
||||
* obtain the appropriate class loader for deserialization.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(ObjectName name, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException;
|
||||
|
||||
@Deprecated(since="1.5")
|
||||
default public ObjectInputStream deserialize(ObjectName name, byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>De-serializes a byte array in the context of a given MBean
|
||||
@ -682,6 +685,8 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* used for the de-serialization.
|
||||
* @param data The byte array to be de-sererialized.
|
||||
*
|
||||
* @implSpec This method throws {@link UnsupportedOperationException} by default.
|
||||
*
|
||||
* @return The de-serialized object stream.
|
||||
*
|
||||
* @exception OperationsException Any of the usual Input/Output
|
||||
@ -692,9 +697,11 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* @deprecated Use {@link #getClassLoaderRepository} to obtain the
|
||||
* class loader repository and use it to deserialize.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className, byte[] data)
|
||||
throws OperationsException, ReflectionException;
|
||||
@Deprecated(since="1.5")
|
||||
default public ObjectInputStream deserialize(String className, byte[] data)
|
||||
throws OperationsException, ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -711,6 +718,8 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* loading the specified class. If null, the MBean Server's class
|
||||
* loader will be used.
|
||||
*
|
||||
* @implSpec This method throws {@link UnsupportedOperationException} by default.
|
||||
*
|
||||
* @return The de-serialized object stream.
|
||||
*
|
||||
* @exception InstanceNotFoundException The specified class loader
|
||||
@ -723,12 +732,14 @@ public interface MBeanServer extends MBeanServerConnection {
|
||||
* @deprecated Use {@link #getClassLoader getClassLoader} to obtain
|
||||
* the class loader for deserialization.
|
||||
*/
|
||||
@Deprecated
|
||||
public ObjectInputStream deserialize(String className,
|
||||
@Deprecated(since="1.5")
|
||||
default public ObjectInputStream deserialize(String className,
|
||||
ObjectName loaderName,
|
||||
byte[] data)
|
||||
throws InstanceNotFoundException, OperationsException,
|
||||
ReflectionException;
|
||||
ReflectionException {
|
||||
throw new UnsupportedOperationException("Not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Return the {@link java.lang.ClassLoader} that was used for
|
||||
|
||||
@ -993,32 +993,39 @@ implements ReferenceType {
|
||||
return minorVersion;
|
||||
}
|
||||
|
||||
private void getConstantPoolInfo() {
|
||||
private byte[] getConstantPoolInfo() {
|
||||
JDWP.ReferenceType.ConstantPool jdwpCPool;
|
||||
if (!vm.canGetConstantPool()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (constantPoolInfoGotten) {
|
||||
return;
|
||||
} else {
|
||||
try {
|
||||
jdwpCPool = JDWP.ReferenceType.ConstantPool.process(vm, this);
|
||||
} catch (JDWPException exc) {
|
||||
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
|
||||
constanPoolCount = 0;
|
||||
constantPoolBytesRef = null;
|
||||
constantPoolInfoGotten = true;
|
||||
return;
|
||||
} else {
|
||||
throw exc.toJDIException();
|
||||
}
|
||||
if (constantPoolBytesRef == null) {
|
||||
return null;
|
||||
}
|
||||
byte[] cpbytes = constantPoolBytesRef.get();
|
||||
if (cpbytes != null) {
|
||||
return cpbytes;
|
||||
}
|
||||
byte[] cpbytes;
|
||||
constanPoolCount = jdwpCPool.count;
|
||||
cpbytes = jdwpCPool.bytes;
|
||||
constantPoolBytesRef = new SoftReference<byte[]>(cpbytes);
|
||||
constantPoolInfoGotten = true;
|
||||
}
|
||||
|
||||
try {
|
||||
jdwpCPool = JDWP.ReferenceType.ConstantPool.process(vm, this);
|
||||
} catch (JDWPException exc) {
|
||||
if (exc.errorCode() == JDWP.Error.ABSENT_INFORMATION) {
|
||||
constanPoolCount = 0;
|
||||
constantPoolBytesRef = null;
|
||||
constantPoolInfoGotten = true;
|
||||
return null;
|
||||
} else {
|
||||
throw exc.toJDIException();
|
||||
}
|
||||
}
|
||||
byte[] cpbytes;
|
||||
constanPoolCount = jdwpCPool.count;
|
||||
cpbytes = jdwpCPool.bytes;
|
||||
constantPoolBytesRef = new SoftReference<byte[]>(cpbytes);
|
||||
constantPoolInfoGotten = true;
|
||||
return cpbytes;
|
||||
}
|
||||
|
||||
public int constantPoolCount() {
|
||||
@ -1031,13 +1038,13 @@ implements ReferenceType {
|
||||
}
|
||||
|
||||
public byte[] constantPool() {
|
||||
byte[] cpbytes;
|
||||
try {
|
||||
getConstantPoolInfo();
|
||||
cpbytes = getConstantPoolInfo();
|
||||
} catch (RuntimeException exc) {
|
||||
throw exc;
|
||||
}
|
||||
if (constantPoolBytesRef != null) {
|
||||
byte[] cpbytes = constantPoolBytesRef.get();
|
||||
if (cpbytes != null) {
|
||||
/*
|
||||
* Arrays are always modifiable, so it is a little unsafe
|
||||
* to return the cached bytecodes directly; instead, we
|
||||
|
||||
@ -328,9 +328,6 @@ com/sun/jdi/GetLocalVariables4Test.sh 8067354 windows-
|
||||
|
||||
com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-all
|
||||
|
||||
com/sun/jdi/ClassesByName2Test.java 8160833 generic-all
|
||||
com/sun/jdi/RedefineCrossEvent.java 8160833 generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_time
|
||||
@ -357,9 +354,11 @@ sun/tools/jcmd/TestJcmdSanity.java 8031482 windows-
|
||||
|
||||
sun/tools/jhsdb/BasicLauncherTest.java 8160376 macosx-all
|
||||
|
||||
sun/tools/jhsdb/HeapDumpTest.java 8160376 macosx-all
|
||||
|
||||
sun/tools/jhsdb/heapconfig/JMapHeapConfigTest.java 8160376 macosx-all
|
||||
|
||||
sun/tools/jps/TestJpsJar.java 8160923 generic-all
|
||||
sun/tools/jps/TestJpsJar.java 8165500 generic-all
|
||||
|
||||
sun/tools/jps/TestJpsJarRelative.java 6456333 generic-all
|
||||
|
||||
|
||||
104
jdk/test/com/sun/jdi/ConstantPoolInfoGC.java
Normal file
104
jdk/test/com/sun/jdi/ConstantPoolInfoGC.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 6822627
|
||||
* @summary Test that ReferenceType.constantPool does not produce an NPE
|
||||
*
|
||||
* @author Egor Ushakov
|
||||
*
|
||||
* @modules jdk.jdi/com.sun.tools.jdi
|
||||
* @run build TestScaffold VMConnection
|
||||
* @run compile -g ConstantPoolInfoGC.java
|
||||
* @run main/othervm ConstantPoolInfoGC
|
||||
*/
|
||||
|
||||
import com.sun.jdi.ReferenceType;
|
||||
import com.sun.tools.jdi.ReferenceTypeImpl;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
|
||||
/********** target program **********/
|
||||
|
||||
class ConstantPoolGCTarg {
|
||||
public static void main(String[] args){
|
||||
System.out.println("Anything");
|
||||
}
|
||||
}
|
||||
|
||||
/********** test program **********/
|
||||
|
||||
public class ConstantPoolInfoGC extends TestScaffold {
|
||||
ReferenceType targetClass;
|
||||
|
||||
ConstantPoolInfoGC(String args[]) {
|
||||
super(args);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new ConstantPoolInfoGC(args).startTests();
|
||||
}
|
||||
|
||||
/********** test core **********/
|
||||
|
||||
protected void runTests() throws Exception {
|
||||
targetClass = startToMain("ConstantPoolGCTarg").location().declaringType();
|
||||
|
||||
if (vm().canGetConstantPool()) {
|
||||
byte[] cpbytes = targetClass.constantPool();
|
||||
|
||||
// imitate SoftReference cleared
|
||||
Field constantPoolBytesRef = ReferenceTypeImpl.class.getDeclaredField("constantPoolBytesRef");
|
||||
constantPoolBytesRef.setAccessible(true);
|
||||
Reference softRef = (Reference) constantPoolBytesRef.get(targetClass);
|
||||
softRef.clear();
|
||||
|
||||
byte[] cpbytes2 = targetClass.constantPool();
|
||||
if (!Arrays.equals(cpbytes, cpbytes2)) {
|
||||
failure("Consequent constantPool results vary, first was : " + cpbytes + ", now: " + cpbytes2);
|
||||
};
|
||||
|
||||
} else {
|
||||
System.out.println("can get constant pool version not supported");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* resume until end
|
||||
*/
|
||||
listenUntilVMDisconnect();
|
||||
|
||||
/*
|
||||
* deal with results of test
|
||||
* if anything has called failure("foo") testFailed will be true
|
||||
*/
|
||||
if (!testFailed) {
|
||||
println("ConstantPoolInfoGC: passed");
|
||||
} else {
|
||||
throw new Exception("ConstantPoolInfoGC: failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,11 +101,8 @@ public class GetModuleTest {
|
||||
return new Object[][] {
|
||||
|
||||
{ GetModuleTest.class, null },
|
||||
{ GetModuleTest[].class, null },
|
||||
{ Object.class, null },
|
||||
{ Object[].class, null },
|
||||
{ Component.class, null },
|
||||
{ Component[].class, null },
|
||||
|
||||
};
|
||||
}
|
||||
@ -117,7 +114,7 @@ public class GetModuleTest {
|
||||
public void testGetModuleOnVMAnonymousClass(Class<?> hostClass, String ignore) {
|
||||
|
||||
// choose a class name in the same package as the host class
|
||||
String prefix = packageName(hostClass);
|
||||
String prefix = hostClass.getPackageName();
|
||||
if (prefix.length() > 0)
|
||||
prefix = prefix.replace('.', '/') + "/";
|
||||
String className = prefix + "Anon";
|
||||
@ -136,17 +133,6 @@ public class GetModuleTest {
|
||||
assertTrue(anonClass.getModule() == hostClass.getModule());
|
||||
}
|
||||
|
||||
private static String packageName(Class<?> c) {
|
||||
if (c.isArray()) {
|
||||
return packageName(c.getComponentType());
|
||||
} else {
|
||||
String name = c.getName();
|
||||
int dot = name.lastIndexOf('.');
|
||||
if (dot == -1) return "";
|
||||
return name.substring(0, dot);
|
||||
}
|
||||
}
|
||||
|
||||
private static int constantPoolSize(byte[] classFile) {
|
||||
return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
|
||||
}
|
||||
|
||||
@ -57,9 +57,9 @@ public class VMAnonymousClass {
|
||||
@Test public void testJavaLangInvoke() throws Throwable { test("java/lang/invoke"); }
|
||||
@Test public void testProhibitedJavaPkg() throws Throwable {
|
||||
try {
|
||||
test("java/prohibited");
|
||||
} catch (SecurityException e) {
|
||||
return;
|
||||
test("java/prohibited");
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("Expected SecurityException");
|
||||
}
|
||||
@ -72,10 +72,17 @@ public class VMAnonymousClass {
|
||||
if (pkg.equals("java/prohibited")) {
|
||||
VMAnonymousClass sampleclass = new VMAnonymousClass();
|
||||
host_class = (Class)sampleclass.getClass();
|
||||
} else if (pkg.equals("java/lang")) {
|
||||
host_class = Object.class;
|
||||
} else if (pkg.equals("java/util")) {
|
||||
host_class = java.util.ArrayList.class;
|
||||
} else if (pkg.equals("jdk/internal/misc")) {
|
||||
host_class = jdk.internal.misc.Signal.class;
|
||||
} else if (pkg.equals("java/lang/invoke")) {
|
||||
host_class = java.lang.invoke.CallSite.class;
|
||||
} else {
|
||||
host_class = Object.class;
|
||||
throw new RuntimeException("Unexpected pkg: " + pkg);
|
||||
}
|
||||
|
||||
// Define VM anonymous class
|
||||
Class anonClass = unsafe.defineAnonymousClass(host_class, bytes, null);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, 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
|
||||
@ -26,27 +26,28 @@
|
||||
* @bug 4530538
|
||||
* @summary Basic unit test of ThreadInfo.getLockName()
|
||||
* and ThreadInfo.getLockOwnerName()
|
||||
* @library /lib/testlibrary
|
||||
* @author Mandy Chung
|
||||
* @author Jaroslav Bachorik
|
||||
*
|
||||
* @library /lib/testlibrary
|
||||
* @modules java.management
|
||||
* @build jdk.testlibrary.*
|
||||
* @run main/othervm Locks
|
||||
*/
|
||||
|
||||
import java.lang.management.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.Phaser;
|
||||
import java.util.function.Predicate;
|
||||
import jdk.testlibrary.LockFreeLogManager;
|
||||
|
||||
public class Locks {
|
||||
private static final Object objA = new Object();
|
||||
private static final Object objB = new Object();
|
||||
private static final Object objC = new Object();
|
||||
private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
|
||||
private static final LockFreeLogManager logger = new LockFreeLogManager();
|
||||
|
||||
private static boolean testFailed = false;
|
||||
private static final Object OBJA = new Object();
|
||||
private static final Object OBJB = new Object();
|
||||
private static final EnhancedWaiter OBJC = new EnhancedWaiter();
|
||||
private static final ThreadMXBean TM = ManagementFactory.getThreadMXBean();
|
||||
private static final LockFreeLogManager LOGGER = new LockFreeLogManager();
|
||||
|
||||
private static String getLockName(Object lock) {
|
||||
if (lock == null) return null;
|
||||
@ -56,67 +57,103 @@ public class Locks {
|
||||
}
|
||||
|
||||
private static void assertNoLock(Thread t) {
|
||||
long tid = t.getId();
|
||||
ThreadInfo info = tm.getThreadInfo(tid);
|
||||
String result = info.getLockName();
|
||||
|
||||
if (result != null) {
|
||||
throw new RuntimeException("Thread " + t.getName() + " is not supposed to hold any lock. " +
|
||||
"Currently owning lock: " + result);
|
||||
if (t == null) {
|
||||
return;
|
||||
}
|
||||
Optional<ThreadInfo> result = Arrays.asList(
|
||||
TM.getThreadInfo(TM.getAllThreadIds(), true, true)).
|
||||
stream().
|
||||
filter(tInfo -> (tInfo != null && tInfo.getLockOwnerName() != null)
|
||||
? tInfo.getLockOwnerName().equals(t.getName()) : false).
|
||||
findAny();
|
||||
if (result.isPresent()) {
|
||||
throw new RuntimeException("Thread " + t.getName() + " is not "
|
||||
+ "supposed to be hold any lock. Currently owning lock : "
|
||||
+ result.get().getLockName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkBlockedObject(Thread t, Object lock, Thread owner,
|
||||
Thread.State expectedState) {
|
||||
long tid = t.getId();
|
||||
ThreadInfo info = tm.getThreadInfo(tid);
|
||||
String result = info.getLockName();
|
||||
String expectedLock = (lock != null ? getLockName(lock) : null);
|
||||
String expectedOwner = (owner != null ? owner.getName() : null);
|
||||
/*
|
||||
* Handy debug function to check if error condition is because of test code or not.
|
||||
*/
|
||||
private static void printStackTrace(Thread thread) {
|
||||
if (thread == null) {
|
||||
return;
|
||||
}
|
||||
StackTraceElement[] stackTrace = thread.getStackTrace();
|
||||
log("Stack dump : Thread -> " + thread.getName());
|
||||
for (StackTraceElement stackTraceEl : stackTrace) {
|
||||
log("\t" + stackTraceEl.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (lock != null) {
|
||||
if (expectedState == Thread.State.BLOCKED) {
|
||||
int retryCount=0;
|
||||
while(info.getThreadState() != Thread.State.BLOCKED) {
|
||||
if (retryCount++ > 500) {
|
||||
throw new RuntimeException("Thread " + t.getName() +
|
||||
" is expected to block on " + expectedLock +
|
||||
" but got " + result +
|
||||
" Thread.State = " + info.getThreadState());
|
||||
}
|
||||
goSleep(100);
|
||||
info = tm.getThreadInfo(tid);
|
||||
result = info.getLockName();
|
||||
private static void assertThreadState(Thread t, Thread.State expectedState) {
|
||||
long tid = t.getId();
|
||||
if (expectedState == Thread.State.BLOCKED
|
||||
&& TM.getThreadInfo(tid).getThreadState() != Thread.State.BLOCKED) {
|
||||
int retryCount = 0;
|
||||
printStackTrace(t);
|
||||
while (TM.getThreadInfo(tid).getThreadState() != Thread.State.BLOCKED) {
|
||||
if (retryCount++ > 500) {
|
||||
printStackTrace(t);
|
||||
throw new RuntimeException("Thread " + t.getName() + " is at "
|
||||
+ TM.getThreadInfo(tid).getThreadState() + " state but is expected to "
|
||||
+ "be in Thread.State = " + expectedState);
|
||||
}
|
||||
}
|
||||
if (expectedState == Thread.State.WAITING &&
|
||||
info.getThreadState() != Thread.State.WAITING) {
|
||||
throw new RuntimeException("Thread " + t.getName() +
|
||||
" is expected to wait on " + expectedLock +
|
||||
" but got " + result +
|
||||
" Thread.State = " + info.getThreadState());
|
||||
goSleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
if ((result != null && !result.equals(expectedLock)) ||
|
||||
(result == null && expectedLock != null)) {
|
||||
throw new RuntimeException("Thread " + t.getName() + " is blocked on " +
|
||||
expectedLock + " but got " + result);
|
||||
}
|
||||
result = info.getLockOwnerName();
|
||||
if ((result != null && !result.equals(expectedOwner)) ||
|
||||
(result == null && expectedOwner != null)) {
|
||||
throw new RuntimeException("Owner of " + lock + " should be " +
|
||||
expectedOwner + " but got " + result);
|
||||
if (!TM.getThreadInfo(tid).getThreadState().equals(expectedState)) {
|
||||
printStackTrace(t);
|
||||
throw new RuntimeException("Thread " + t.getName() + " is at "
|
||||
+ TM.getThreadInfo(tid).getThreadState() + " state but is expected to "
|
||||
+ "be in Thread.State = " + expectedState);
|
||||
}
|
||||
}
|
||||
|
||||
private static void goSleep(long ms) {
|
||||
/*
|
||||
* Do slow check if thread is blocked on a lock. It is possible that last thread
|
||||
* to come out of Phaser might still be in Phaser call stack (Unsafe.park) and
|
||||
* hence might eventually acquire expected lock.
|
||||
*/
|
||||
private static void checkBlockedObject(Thread t, Object lock, Thread owner) {
|
||||
long tid = t.getId();
|
||||
String result = TM.getThreadInfo(tid).getLockName();
|
||||
final String expectedLock = (lock != null ? getLockName(lock) : null);
|
||||
Predicate<String> p = (res) -> ((res != null && !res.equals(expectedLock))
|
||||
|| (res == null && expectedLock != null));
|
||||
|
||||
if (p.test(result)) {
|
||||
printStackTrace(t);
|
||||
int retryCount = 0;
|
||||
while (p.test(result)) {
|
||||
if (retryCount++ > 500) {
|
||||
printStackTrace(t);
|
||||
throw new RuntimeException("Thread " + t.getName() + " is blocked on "
|
||||
+ expectedLock + " but got " + result);
|
||||
}
|
||||
goSleep(100);
|
||||
result = TM.getThreadInfo(tid).getLockName();
|
||||
}
|
||||
}
|
||||
|
||||
result = TM.getThreadInfo(tid).getLockOwnerName();
|
||||
final String expectedOwner = (owner != null ? owner.getName() : null);
|
||||
|
||||
p = (res) -> ((res != null && !res.equals(expectedOwner))
|
||||
|| (res == null && expectedOwner != null));
|
||||
if (p.test(result)) {
|
||||
printStackTrace(t);
|
||||
throw new RuntimeException("Owner of " + lock + " should be "
|
||||
+ expectedOwner + " but got " + result);
|
||||
}
|
||||
}
|
||||
|
||||
private static void goSleep(long ms){
|
||||
try {
|
||||
Thread.sleep(ms);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
testFailed = true;
|
||||
} catch (InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,14 +165,15 @@ public class Locks {
|
||||
super("LockAThread");
|
||||
this.p = p;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized(objA) {
|
||||
// stop here for LockBThread to hold objB
|
||||
log("LockAThread about to block on objB");
|
||||
synchronized(OBJA) {
|
||||
// block here while LockBThread holds OBJB
|
||||
log("LockAThread about to block on OBJB");
|
||||
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
|
||||
synchronized(objB) {
|
||||
synchronized(OBJB) {
|
||||
dummyCounter++;
|
||||
};
|
||||
}
|
||||
}
|
||||
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
|
||||
log("LockAThread about to exit");
|
||||
@ -150,14 +188,15 @@ public class Locks {
|
||||
super("LockBThread");
|
||||
this.p = p;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized(objB) {
|
||||
log("LockBThread about to block on objC");
|
||||
synchronized(OBJB) {
|
||||
log("LockBThread about to block on OBJC");
|
||||
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
|
||||
// Signal main thread about to block on objC
|
||||
synchronized(objC) {
|
||||
// Signal main thread about to block on OBJC
|
||||
synchronized(OBJC) {
|
||||
dummyCounter++;
|
||||
};
|
||||
}
|
||||
}
|
||||
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
|
||||
log("LockBThread about to exit");
|
||||
@ -166,9 +205,30 @@ public class Locks {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be invoked from within a synchronized context
|
||||
*/
|
||||
private static class EnhancedWaiter {
|
||||
|
||||
boolean isNotified = false;
|
||||
|
||||
public void doWait() throws InterruptedException {
|
||||
while (!isNotified) {
|
||||
wait();
|
||||
}
|
||||
isNotified = false;
|
||||
}
|
||||
|
||||
public void doNotify() {
|
||||
isNotified = true;
|
||||
notify();
|
||||
}
|
||||
}
|
||||
|
||||
private static WaitingThread waiter;
|
||||
private static final Object ready = new Object();
|
||||
private static CheckerThread checker;
|
||||
|
||||
static class WaitingThread extends Thread {
|
||||
private final Phaser p;
|
||||
|
||||
@ -180,17 +240,16 @@ public class Locks {
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized(objC) {
|
||||
log("WaitingThread about to wait on objC");
|
||||
synchronized(OBJC) {
|
||||
log("WaitingThread about to wait on OBJC");
|
||||
try {
|
||||
// Signal checker thread, about to wait on objC.
|
||||
// Signal checker thread, about to wait on OBJC.
|
||||
waiting = false;
|
||||
p.arriveAndAwaitAdvance(); // Phase 1 (waiting)
|
||||
waiting = true;
|
||||
objC.wait();
|
||||
OBJC.doWait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
testFailed = true;
|
||||
throw new RuntimeException(e); // Do not continue test
|
||||
}
|
||||
|
||||
// block until CheckerThread finishes checking
|
||||
@ -202,19 +261,18 @@ public class Locks {
|
||||
dummyCounter++;
|
||||
}
|
||||
}
|
||||
synchronized(objC) {
|
||||
synchronized(OBJC) {
|
||||
try {
|
||||
// signal checker thread, about to wait on objC
|
||||
// signal checker thread, about to wait on OBJC
|
||||
waiting = false;
|
||||
p.arriveAndAwaitAdvance(); // Phase 3 (waiting)
|
||||
waiting = true;
|
||||
objC.wait();
|
||||
OBJC.doWait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
testFailed = true;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
log("WaitingThread about to exit waiting on objC 2");
|
||||
log("WaitingThread about to exit waiting on OBJC 2");
|
||||
}
|
||||
|
||||
public void waitForWaiting() {
|
||||
@ -241,85 +299,87 @@ public class Locks {
|
||||
super("CheckerThread");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (ready) {
|
||||
// wait until WaitingThread about to wait for objC
|
||||
synchronized(ready) {
|
||||
// wait until WaitingThread about to wait for OBJC
|
||||
waiter.waitForWaiting(); // Phase 1 (waiting)
|
||||
checkBlockedObject(waiter, objC, null, Thread.State.WAITING);
|
||||
assertThreadState(waiter, Thread.State.WAITING);
|
||||
checkBlockedObject(waiter, OBJC, null);
|
||||
|
||||
synchronized (objC) {
|
||||
objC.notify();
|
||||
synchronized(OBJC) {
|
||||
OBJC.doNotify();
|
||||
}
|
||||
|
||||
// wait for waiter thread to about to enter
|
||||
// synchronized object ready.
|
||||
waiter.waitForBlocked(); // Phase 2 (waiting)
|
||||
checkBlockedObject(waiter, ready, this, Thread.State.BLOCKED);
|
||||
assertThreadState(waiter, Thread.State.BLOCKED);
|
||||
checkBlockedObject(waiter, ready, this);
|
||||
}
|
||||
|
||||
// wait for signal from waiting thread that it is about
|
||||
// wait for objC.
|
||||
// wait for OBJC.
|
||||
waiter.waitForWaiting(); // Phase 3 (waiting)
|
||||
synchronized(objC) {
|
||||
checkBlockedObject(waiter, objC, Thread.currentThread(), Thread.State.WAITING);
|
||||
objC.notify();
|
||||
synchronized(OBJC) {
|
||||
assertThreadState(waiter, Thread.State.WAITING);
|
||||
checkBlockedObject(waiter, OBJC, Thread.currentThread());
|
||||
OBJC.doNotify();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
Thread mainThread = Thread.currentThread();
|
||||
|
||||
// Test uncontested case
|
||||
LockAThread t1;
|
||||
LockBThread t2;
|
||||
|
||||
Phaser p = new Phaser(3);
|
||||
synchronized(objC) {
|
||||
// Make sure the main thread is not holding any lock
|
||||
assertNoLock(mainThread);
|
||||
|
||||
// Test deadlock case
|
||||
// t1 holds lockA and attempts to lock B
|
||||
// t2 holds lockB and attempts to lock C
|
||||
|
||||
t1 = new LockAThread(p);
|
||||
t1.start();
|
||||
|
||||
t2 = new LockBThread(p);
|
||||
t2.start();
|
||||
|
||||
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
|
||||
checkBlockedObject(t2, objC, mainThread, Thread.State.BLOCKED);
|
||||
checkBlockedObject(t1, objB, t2, Thread.State.BLOCKED);
|
||||
|
||||
long[] expectedThreads = new long[3];
|
||||
expectedThreads[0] = t1.getId(); // blocked on lockB
|
||||
expectedThreads[1] = t2.getId(); // owner of lockB blocking on lockC
|
||||
expectedThreads[2] = mainThread.getId(); // owner of lockC
|
||||
findThreadsBlockedOn(objB, expectedThreads);
|
||||
}
|
||||
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
|
||||
|
||||
p = new Phaser(2);
|
||||
// Test Object.wait() case
|
||||
waiter = new WaitingThread(p);
|
||||
waiter.start();
|
||||
|
||||
checker = new CheckerThread();
|
||||
checker.start();
|
||||
|
||||
try {
|
||||
waiter.join();
|
||||
checker.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
testFailed = true;
|
||||
}
|
||||
Thread mainThread = Thread.currentThread();
|
||||
|
||||
if (testFailed) {
|
||||
throw new RuntimeException("TEST FAILED.");
|
||||
// Test uncontested case
|
||||
LockAThread t1;
|
||||
LockBThread t2;
|
||||
|
||||
Phaser p = new Phaser(3);
|
||||
synchronized(OBJC) {
|
||||
// Make sure the main thread is not holding any lock
|
||||
assertNoLock(mainThread);
|
||||
|
||||
// Test deadlock case
|
||||
// t1 holds lockA and attempts to lock B
|
||||
// t2 holds lockB and attempts to lock C
|
||||
t1 = new LockAThread(p);
|
||||
t1.start();
|
||||
|
||||
t2 = new LockBThread(p);
|
||||
t2.start();
|
||||
|
||||
p.arriveAndAwaitAdvance(); // Phase 1 (blocking)
|
||||
assertThreadState(t2, Thread.State.BLOCKED);
|
||||
checkBlockedObject(t2, OBJC, mainThread);
|
||||
assertThreadState(t1, Thread.State.BLOCKED);
|
||||
checkBlockedObject(t1, OBJB, t2);
|
||||
|
||||
long[] expectedThreads = new long[3];
|
||||
expectedThreads[0] = t1.getId(); // blocked on lockB
|
||||
expectedThreads[1] = t2.getId(); // owner of lockB blocking on lockC
|
||||
expectedThreads[2] = mainThread.getId(); // owner of lockC
|
||||
findThreadsBlockedOn(OBJB, expectedThreads);
|
||||
}
|
||||
p.arriveAndAwaitAdvance(); // Phase 2 (blocking)
|
||||
|
||||
p = new Phaser(2);
|
||||
// Test Object.wait() case
|
||||
waiter = new WaitingThread(p);
|
||||
waiter.start();
|
||||
|
||||
checker = new CheckerThread();
|
||||
checker.start();
|
||||
|
||||
try {
|
||||
waiter.join();
|
||||
checker.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally { // log all the messages to STDOUT
|
||||
System.out.println(LOGGER.toString());
|
||||
}
|
||||
System.out.println("Test passed.");
|
||||
}
|
||||
@ -335,9 +395,9 @@ public class Locks {
|
||||
throw new RuntimeException("TEST FAILED: " +
|
||||
lock + " expected to have owner");
|
||||
}
|
||||
for (int j = 0; j < infos.length; j++) {
|
||||
if (infos[j].getThreadId() == threadId) {
|
||||
ownerInfo = infos[j];
|
||||
for (ThreadInfo info1 : infos) {
|
||||
if (info1.getThreadId() == threadId) {
|
||||
ownerInfo = info1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -349,11 +409,11 @@ public class Locks {
|
||||
throws Exception {
|
||||
String lock = getLockName(o);
|
||||
// Check with ThreadInfo with no stack trace (i.e. no safepoint)
|
||||
ThreadInfo[] infos = tm.getThreadInfo(tm.getAllThreadIds());
|
||||
ThreadInfo[] infos = TM.getThreadInfo(TM.getAllThreadIds());
|
||||
doCheck(infos, lock, expectedThreads);
|
||||
|
||||
// Check with ThreadInfo with stack trace
|
||||
infos = tm.getThreadInfo(tm.getAllThreadIds(), 1);
|
||||
infos = TM.getThreadInfo(TM.getAllThreadIds(), 1);
|
||||
doCheck(infos, lock, expectedThreads);
|
||||
}
|
||||
|
||||
@ -376,7 +436,7 @@ public class Locks {
|
||||
long[] threads = new long[10];
|
||||
int count = 0;
|
||||
threads[count++] = ownerInfo.getThreadId();
|
||||
while (ownerInfo != null && ownerInfo.getThreadState() == Thread.State.BLOCKED) {
|
||||
while (ownerInfo.getThreadState() == Thread.State.BLOCKED) {
|
||||
ownerInfo = findOwnerInfo(infos, lock);
|
||||
threads[count++] = ownerInfo.getThreadId();
|
||||
log(" Owner = %s id = %d",
|
||||
@ -407,6 +467,6 @@ public class Locks {
|
||||
}
|
||||
|
||||
private static void log(String format, Object ... args) {
|
||||
logger.log(format + "%n", args);
|
||||
LOGGER.log(format + "%n", args);
|
||||
}
|
||||
}
|
||||
|
||||
111
jdk/test/jdk/internal/misc/Unsafe/TestBadHostClass.java
Normal file
111
jdk/test/jdk/internal/misc/Unsafe/TestBadHostClass.java
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 8058575
|
||||
* @summary Test that bad host classes cause exceptions to get thrown.
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.base/jdk.internal.org.objectweb.asm
|
||||
* @run main TestBadHostClass
|
||||
*/
|
||||
|
||||
|
||||
import java.lang.*;
|
||||
import java.lang.reflect.Field;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
import jdk.test.lib.unsafe.UnsafeHelper;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import static jdk.internal.org.objectweb.asm.Opcodes.*;
|
||||
|
||||
// Test that bad host classes cause exceptions.
|
||||
public class TestBadHostClass {
|
||||
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
|
||||
private static String packageName(Class<?> c) {
|
||||
if (c.isArray()) {
|
||||
return packageName(c.getComponentType());
|
||||
} else {
|
||||
String name = c.getName();
|
||||
int dot = name.lastIndexOf('.');
|
||||
if (dot == -1) return "";
|
||||
return name.substring(0, dot);
|
||||
}
|
||||
}
|
||||
|
||||
private static int constantPoolSize(byte[] classFile) {
|
||||
return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
|
||||
}
|
||||
|
||||
static public void badHostClass(Class<?> hostClass) {
|
||||
// choose a class name in the same package as the host class
|
||||
String className;
|
||||
if (hostClass != null) {
|
||||
String prefix = packageName(hostClass);
|
||||
if (prefix.length() > 0)
|
||||
prefix = prefix.replace('.', '/') + "/";
|
||||
className = prefix + "Anon";
|
||||
} else {
|
||||
className = "Anon";
|
||||
}
|
||||
|
||||
// create the class
|
||||
String superName = "java/lang/Object";
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
|
||||
+ ClassWriter.COMPUTE_FRAMES);
|
||||
cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
|
||||
className, null, superName, null);
|
||||
byte[] classBytes = cw.toByteArray();
|
||||
int cpPoolSize = constantPoolSize(classBytes);
|
||||
Class<?> anonClass
|
||||
= unsafe.defineAnonymousClass(hostClass, classBytes, new Object[cpPoolSize]);
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// host class is an array of java.lang.Objects.
|
||||
try {
|
||||
badHostClass(Object[].class);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
}
|
||||
|
||||
// host class is an array of objects of this class.
|
||||
try {
|
||||
badHostClass(TestBadHostClass[].class);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
}
|
||||
|
||||
// host class is null.
|
||||
try {
|
||||
badHostClass(null);
|
||||
} catch (NullPointerException ex) {
|
||||
}
|
||||
|
||||
// host class is a primitive array class.
|
||||
try {
|
||||
badHostClass(int[].class);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2016, 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
|
||||
@ -69,7 +69,7 @@ public class FileInputStreamPoolTest {
|
||||
// make JVM process References
|
||||
System.gc();
|
||||
// help ReferenceHandler thread enqueue References
|
||||
while (TestProxy.Reference_tryHandlePending(false)) {}
|
||||
while (TestProxy.Reference_waitForReferenceProcessing()) { }
|
||||
// help run Finalizers
|
||||
System.runFinalization();
|
||||
}
|
||||
@ -103,11 +103,11 @@ public class FileInputStreamPoolTest {
|
||||
/**
|
||||
* A proxy for (package)private static methods:
|
||||
* sun.security.provider.FileInputStreamPool.getInputStream
|
||||
* java.lang.ref.Reference.tryHandlePending
|
||||
* java.lang.ref.Reference.waitForReferenceProcessing
|
||||
*/
|
||||
static class TestProxy {
|
||||
private static final Method getInputStreamMethod;
|
||||
private static final Method tryHandlePendingMethod;
|
||||
private static final Method waitForReferenceProcessingMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
@ -118,9 +118,9 @@ public class FileInputStreamPoolTest {
|
||||
"getInputStream", File.class);
|
||||
getInputStreamMethod.setAccessible(true);
|
||||
|
||||
tryHandlePendingMethod = Reference.class.getDeclaredMethod(
|
||||
"tryHandlePending", boolean.class);
|
||||
tryHandlePendingMethod.setAccessible(true);
|
||||
waitForReferenceProcessingMethod =
|
||||
Reference.class.getDeclaredMethod("waitForReferenceProcessing");
|
||||
waitForReferenceProcessingMethod.setAccessible(true);
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
@ -146,13 +146,14 @@ public class FileInputStreamPoolTest {
|
||||
}
|
||||
}
|
||||
|
||||
static boolean Reference_tryHandlePending(boolean waitForNotify) {
|
||||
static boolean Reference_waitForReferenceProcessing() {
|
||||
try {
|
||||
return (boolean) tryHandlePendingMethod
|
||||
.invoke(null, waitForNotify);
|
||||
return (boolean) waitForReferenceProcessingMethod.invoke(null);
|
||||
} catch (InvocationTargetException e) {
|
||||
Throwable te = e.getTargetException();
|
||||
if (te instanceof RuntimeException) {
|
||||
if (te instanceof InterruptedException) {
|
||||
return true;
|
||||
} else if (te instanceof RuntimeException) {
|
||||
throw (RuntimeException) te;
|
||||
} else if (te instanceof Error) {
|
||||
throw (Error) te;
|
||||
|
||||
@ -31,12 +31,10 @@
|
||||
* @run main BasicLauncherTest
|
||||
*/
|
||||
|
||||
import static jdk.testlibrary.Asserts.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
@ -84,15 +82,56 @@ public class BasicLauncherTest {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
|
||||
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Process toolProcess = processBuilder.start();
|
||||
toolProcess.getOutputStream().write("quit\n".getBytes());
|
||||
toolProcess.getOutputStream().close();
|
||||
|
||||
try (OutputStream out = toolProcess.getOutputStream()) {
|
||||
out.write("universe\n".getBytes());
|
||||
out.write("printmdo -a\n".getBytes());
|
||||
out.write("quit\n".getBytes());
|
||||
}
|
||||
|
||||
// By default child process output stream redirected to pipe, so we are reading it in foreground.
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(toolProcess.getInputStream()));
|
||||
Exception unexpected = null;
|
||||
try (BufferedReader reader =
|
||||
new BufferedReader(new InputStreamReader(toolProcess.getInputStream()))) {
|
||||
String line;
|
||||
String unexpectedMsg =
|
||||
"One or more of 'VirtualCallData', 'CounterData', " +
|
||||
"'ReceiverTypeData', 'bci', 'MethodData' " +
|
||||
"or 'java/lang/Object' not found";
|
||||
boolean knownClassFound = false;
|
||||
boolean knownProfileDataTypeFound = false;
|
||||
boolean knownTokensFound = false;
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line.trim());
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
System.out.println(line);
|
||||
|
||||
if (line.contains("unknown subtype of CollectedHeap")) {
|
||||
unexpected = new RuntimeException("CollectedHeap type should be known.");
|
||||
break;
|
||||
}
|
||||
else if (line.contains("missing reason for ")) {
|
||||
unexpected = new RuntimeException("missing reason for ");
|
||||
break;
|
||||
}
|
||||
if (line.contains("VirtualCallData") ||
|
||||
line.contains("CounterData") ||
|
||||
line.contains("ReceiverTypeData")) {
|
||||
knownProfileDataTypeFound = true;
|
||||
}
|
||||
if (line.contains("bci") ||
|
||||
line.contains("MethodData")) {
|
||||
knownTokensFound = true;
|
||||
}
|
||||
if (line.contains("java/lang/Object")) {
|
||||
knownClassFound = true;
|
||||
}
|
||||
}
|
||||
if ((knownClassFound == false) ||
|
||||
(knownTokensFound == false) ||
|
||||
(knownProfileDataTypeFound == false)) {
|
||||
unexpected = new RuntimeException(unexpectedMsg);
|
||||
}
|
||||
}
|
||||
|
||||
toolProcess.waitFor();
|
||||
@ -100,6 +139,14 @@ public class BasicLauncherTest {
|
||||
if (toolProcess.exitValue() != 0) {
|
||||
throw new RuntimeException("FAILED CLHSDB terminated with non-zero exit code " + toolProcess.exitValue());
|
||||
}
|
||||
|
||||
if (unexpected != null) {
|
||||
throw unexpected;
|
||||
}
|
||||
|
||||
if (unexpected != null) {
|
||||
throw unexpected;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Test ERROR " + ex, ex);
|
||||
} finally {
|
||||
@ -183,21 +230,6 @@ public class BasicLauncherTest {
|
||||
Arrays.asList(toolArgs));
|
||||
}
|
||||
|
||||
public static void testHeapDump() throws IOException {
|
||||
File dump = new File("jhsdb.jmap.dump." +
|
||||
System.currentTimeMillis() + ".hprof");
|
||||
if (dump.exists()) {
|
||||
dump.delete();
|
||||
}
|
||||
dump.deleteOnExit();
|
||||
|
||||
launch("heap written to", null, "jmap",
|
||||
"--binaryheap", "--dumpfile=" + dump.getAbsolutePath());
|
||||
|
||||
assertTrue(dump.exists() && dump.isFile(),
|
||||
"Could not create dump file " + dump.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException {
|
||||
|
||||
@ -216,8 +248,6 @@ public class BasicLauncherTest {
|
||||
"System Properties info not available", "jinfo");
|
||||
launch("java.threads", null, "jsnap");
|
||||
|
||||
testHeapDump();
|
||||
|
||||
// The test throws RuntimeException on error.
|
||||
// IOException is thrown if LingeredApp can't start because of some bad
|
||||
// environment condition
|
||||
|
||||
129
jdk/test/sun/tools/jhsdb/HeapDumpTest.java
Normal file
129
jdk/test/sun/tools/jhsdb/HeapDumpTest.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 8163346
|
||||
* @summary Test hashing of extended characters in Serviceability Agent.
|
||||
* @library /test/lib
|
||||
* @library /lib/testlibrary
|
||||
* @compile -encoding utf8 HeapDumpTest.java
|
||||
* @run main/timeout=240 HeapDumpTest
|
||||
*/
|
||||
|
||||
import static jdk.testlibrary.Asserts.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import jdk.testlibrary.JDKToolLauncher;
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.testlibrary.Platform;
|
||||
|
||||
public class HeapDumpTest {
|
||||
|
||||
private static LingeredAppWithExtendedChars theApp = null;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param vmArgs - tool arguments to launch jhsdb
|
||||
* @return exit code of tool
|
||||
*/
|
||||
public static void launch(String expectedMessage, List<String> toolArgs)
|
||||
throws IOException {
|
||||
|
||||
System.out.println("Starting LingeredApp");
|
||||
try {
|
||||
theApp = new LingeredAppWithExtendedChars();
|
||||
LingeredApp.startApp(Arrays.asList("-Xmx256m"), theApp);
|
||||
|
||||
System.out.println(theApp.\u00CB);
|
||||
System.out.println("Starting " + toolArgs.get(0) + " against " + theApp.getPid());
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
|
||||
|
||||
for (String cmd : toolArgs) {
|
||||
launcher.addToolArg(cmd);
|
||||
}
|
||||
|
||||
launcher.addToolArg("--pid=" + Long.toString(theApp.getPid()));
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
|
||||
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(processBuilder);
|
||||
System.out.println("stdout:");
|
||||
System.out.println(output.getStdout());
|
||||
System.out.println("stderr:");
|
||||
System.out.println(output.getStderr());
|
||||
output.shouldContain(expectedMessage);
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Test ERROR " + ex, ex);
|
||||
} finally {
|
||||
LingeredApp.stopApp(theApp);
|
||||
}
|
||||
}
|
||||
|
||||
public static void launch(String expectedMessage, String... toolArgs)
|
||||
throws IOException {
|
||||
|
||||
launch(expectedMessage, Arrays.asList(toolArgs));
|
||||
}
|
||||
|
||||
public static void testHeapDump() throws IOException {
|
||||
File dump = new File("jhsdb.jmap.heap." +
|
||||
System.currentTimeMillis() + ".hprof");
|
||||
if (dump.exists()) {
|
||||
dump.delete();
|
||||
}
|
||||
|
||||
launch("heap written to", "jmap",
|
||||
"--binaryheap", "--dumpfile=" + dump.getAbsolutePath());
|
||||
|
||||
assertTrue(dump.exists() && dump.isFile(),
|
||||
"Could not create dump file " + dump.getAbsolutePath());
|
||||
|
||||
dump.delete();
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException {
|
||||
|
||||
if (!Platform.shouldSAAttach()) {
|
||||
// Silently skip the test if we don't have enough permissions to attach
|
||||
System.err.println("Error! Insufficient permissions to attach - test skipped.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
testHeapDump();
|
||||
|
||||
// The test throws RuntimeException on error.
|
||||
// IOException is thrown if LingeredApp can't start because of some bad
|
||||
// environment condition
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
}
|
||||
32
jdk/test/sun/tools/jhsdb/LingeredAppWithExtendedChars.java
Normal file
32
jdk/test/sun/tools/jhsdb/LingeredAppWithExtendedChars.java
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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 jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
public class LingeredAppWithExtendedChars extends LingeredApp {
|
||||
|
||||
public static int \u00CB = 1;
|
||||
|
||||
public static void main(String args[]) {
|
||||
LingeredApp.main(args);
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ import jdk.testlibrary.ProcessTools;
|
||||
* @library /lib/testlibrary
|
||||
* @modules jdk.jartool/sun.tools.jar
|
||||
* java.management
|
||||
* @build jdk.testlibrary.* JpsHelper JpsBase
|
||||
* @build JpsHelper JpsBase
|
||||
* @run main/othervm TestJpsJar
|
||||
*/
|
||||
public class TestJpsJar {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user