8199643: [TESTBUG] Open source common VM testbase code
authoriignatyev
Mon, 30 Apr 2018 18:10:24 -0700
changeset 49934 44839fbb20db
parent 49933 c63bdf53a1a7
child 49935 2ace90aec488
8199643: [TESTBUG] Open source common VM testbase code Reviewed-by: vlivanov, erikj, mseledtsov, gthornbr
make/test/JtregNativeHotspot.gmk
test/hotspot/jtreg/vmTestbase/ExecDriver.java
test/hotspot/jtreg/vmTestbase/PropertyResolvingWrapper.java
test/hotspot/jtreg/vmTestbase/README.md
test/hotspot/jtreg/vmTestbase/nsk/share/AbstractGoldChecker.java
test/hotspot/jtreg/vmTestbase/nsk/share/ArgumentParser.java
test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java
test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java
test/hotspot/jtreg/vmTestbase/nsk/share/Consts.java
test/hotspot/jtreg/vmTestbase/nsk/share/CustomClassLoader.java
test/hotspot/jtreg/vmTestbase/nsk/share/Debug.java
test/hotspot/jtreg/vmTestbase/nsk/share/Denotation.java
test/hotspot/jtreg/vmTestbase/nsk/share/DummyClassLoader.java
test/hotspot/jtreg/vmTestbase/nsk/share/Failure.java
test/hotspot/jtreg/vmTestbase/nsk/share/FileUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizable.java
test/hotspot/jtreg/vmTestbase/nsk/share/FinalizableObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/Finalizer.java
test/hotspot/jtreg/vmTestbase/nsk/share/GoldChecker.java
test/hotspot/jtreg/vmTestbase/nsk/share/Grep.java
test/hotspot/jtreg/vmTestbase/nsk/share/Harakiri.java
test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.c
test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.h
test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.c
test/hotspot/jtreg/vmTestbase/nsk/share/LocalProcess.java
test/hotspot/jtreg/vmTestbase/nsk/share/Log.java
test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/ObjectInstancesManager.java
test/hotspot/jtreg/vmTestbase/nsk/share/Oddity.java
test/hotspot/jtreg/vmTestbase/nsk/share/Pair.java
test/hotspot/jtreg/vmTestbase/nsk/share/Paragrep.java
test/hotspot/jtreg/vmTestbase/nsk/share/PrintProperties.java
test/hotspot/jtreg/vmTestbase/nsk/share/RASagent.java
test/hotspot/jtreg/vmTestbase/nsk/share/README
test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObjectSet.java
test/hotspot/jtreg/vmTestbase/nsk/share/StringGoldChecker.java
test/hotspot/jtreg/vmTestbase/nsk/share/TestBug.java
test/hotspot/jtreg/vmTestbase/nsk/share/TestFailure.java
test/hotspot/jtreg/vmTestbase/nsk/share/TestJNIError.java
test/hotspot/jtreg/vmTestbase/nsk/share/TimeoutHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java
test/hotspot/jtreg/vmTestbase/nsk/share/Wicket.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODRunnerArgParser.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTargetArgParser.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AbstractJarAgent.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentInformation.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentsAttacher.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/DummyTargetApplication.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/ProcessExecutor.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/TargetApplicationWaitingAgents.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/Utils.java
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.c
test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.h
test/hotspot/jtreg/vmTestbase/nsk/share/classload/ClassPathNonDelegatingClassLoader.java
test/hotspot/jtreg/vmTestbase/nsk/share/classload/GeneratingClassLoader.java
test/hotspot/jtreg/vmTestbase/nsk/share/classload/TemplateClass.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Algorithms.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllMemoryObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ArgumentHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Cell.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/CircularLinkedList.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ClassChain.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinMemoryObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinMemoryObject1.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParams.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParamsAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCTestBase.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/IndexPair.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/LinkedMemoryObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Matrix.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/MemoryObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/OOMStress.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/ThreadedGCTest.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/TwoFieldsObject.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/classes/Classes.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/DerivedProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/DerivedStrategyProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducer1Aware.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducerAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/MemoryStrategy.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/MemoryStrategyAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/RandomProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ArrayOfProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/BooleanArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ByteArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/CharArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/DoubleArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/FloatArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/IntArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/LongArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ObjectArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ShortArrayProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/classload/GeneratedClassProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/list/CircularListProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/list/LinearListProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/TraceProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/TwoFieldsObjectProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/AllMemoryObjectProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/FinMemoryObject1Producer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/FinMemoryObjectProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/MemoryObjectProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/InternedStringProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/RandomStringProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/SimpleStringProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/tree/NonbranchyTreeProducer.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionObjectLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionTimedLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/Locker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/LockerUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/Lockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/LockersAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/MultiLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/JNILockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLockers.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/tree/Tree.java
test/hotspot/jtreg/vmTestbase/nsk/share/gc/tree/TreeNode.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/AbstractJDIDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ConnectorTest.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/DebuggeeEventData.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/DebuggerEventData.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventFilters.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventTestTemplates.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ForceEarlyReturnDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIEventsDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIEventsDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MockReferenceType.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MonitorEnterExecutor.c
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MonitorEventsDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/OwnedMonitorsDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/OwnedMonitorsDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/PlugConnectors.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/PlugTransportService.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestClass1.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestClass2.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestDebuggerType1.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestDebuggerType2.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestInterfaceImplementer1.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ThreadState.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/InstallSDE.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SDEDebuggee.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SDEDebugger.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SmapGenerator.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SmapStratum.java
test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/TestClass1.java
test/hotspot/jtreg/vmTestbase/nsk/share/jni/JNIreferences.c
test/hotspot/jtreg/vmTestbase/nsk/share/jni/README
test/hotspot/jtreg/vmTestbase/nsk/share/jni/jni_tools.c
test/hotspot/jtreg/vmTestbase/nsk/share/jni/jni_tools.h
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ConversionUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/SocketConnection.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/SocketIOPipe.java
test/hotspot/jtreg/vmTestbase/nsk/share/jpda/StateTestThread.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockMaker.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockedThread.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/JNIMonitorLocker.c
test/hotspot/jtreg/vmTestbase/nsk/share/locks/JNIMonitorLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockType.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockingThread.c
test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockingThread.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/MonitorLockingThread.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/ReentrantLockLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/SynchronizedBlockLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/locks/SynchronizedMethodLocker.java
test/hotspot/jtreg/vmTestbase/nsk/share/log/Log.java
test/hotspot/jtreg/vmTestbase/nsk/share/log/LogAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/log/LogSupport.java
test/hotspot/jtreg/vmTestbase/nsk/share/native/README
test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.c
test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.h
test/hotspot/jtreg/vmTestbase/nsk/share/native/native_utils.c
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.c
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.h
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_mutex.c
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_mutex.h
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.c
test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.h
test/hotspot/jtreg/vmTestbase/nsk/share/runner/FinRunner.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/GCRunner.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/MemDiag.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/MultiRunner.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/MultiRunnerAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/RunParams.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/RunParamsAware.java
test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java
test/hotspot/jtreg/vmTestbase/nsk/share/sysdict/ClassLoadersBTree.java
test/hotspot/jtreg/vmTestbase/nsk/share/sysdict/ClassLoadersChain.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/Dumpable.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/ExecutionController.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/Initializable.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyFormatString.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyIntArrayToString.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyObjectArrayToString.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/LocalRandom.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/StressOptions.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/Test.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/TestBase.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/TestExitCode.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/TestUtils.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/Tests.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutHandler.java
test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutWatchdog.java
test/hotspot/jtreg/vmTestbase/vm/share/CommentedFileReader.java
test/hotspot/jtreg/vmTestbase/vm/share/FileUtils.java
test/hotspot/jtreg/vmTestbase/vm/share/InMemoryJavaCompiler.java
test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.c
test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.java
test/hotspot/jtreg/vmTestbase/vm/share/RandomEx.java
test/hotspot/jtreg/vmTestbase/vm/share/StringUtils.java
test/hotspot/jtreg/vmTestbase/vm/share/UnsafeAccess.java
test/hotspot/jtreg/vmTestbase/vm/share/VMRuntimeEnvUtils.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingHeap.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingHelper.java
test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingWithWhiteBox.java
test/hotspot/jtreg/vmTestbase/vm/share/libProcessUtils.c
test/hotspot/jtreg/vmTestbase/vm/share/monitoring/MemoryPoolFinder.java
test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryManagerData.java
test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryPoolData.java
test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryUsageData.java
test/hotspot/jtreg/vmTestbase/vm/share/options/BasicObjectFactory.java
test/hotspot/jtreg/vmTestbase/vm/share/options/BasicOptionObjectFactory.java
test/hotspot/jtreg/vmTestbase/vm/share/options/FClass.java
test/hotspot/jtreg/vmTestbase/vm/share/options/Factory.java
test/hotspot/jtreg/vmTestbase/vm/share/options/IgnoreUnknownArgumentsHandler.java
test/hotspot/jtreg/vmTestbase/vm/share/options/ObjectFactory.java
test/hotspot/jtreg/vmTestbase/vm/share/options/Option.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionDefinition.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionError.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionHandler.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionObjectFactory.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionSupport.java
test/hotspot/jtreg/vmTestbase/vm/share/options/Options.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionsMap.java
test/hotspot/jtreg/vmTestbase/vm/share/options/OptionsSetup.java
test/hotspot/jtreg/vmTestbase/vm/share/options/ParserException.java
test/hotspot/jtreg/vmTestbase/vm/share/options/PrimitiveParser.java
test/hotspot/jtreg/vmTestbase/vm/share/options/package-info.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/BasicObjectFactoryUsageExample.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/ExampleWithNonprimitiveOptions.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/SimpleExample.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/SimpleExampleWithOptionsAnnotation.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/SubClassExample.java
test/hotspot/jtreg/vmTestbase/vm/share/options/test/package-info.java
test/hotspot/jtreg/vmTestbase/vm/share/process/CmdExecutor.java
test/hotspot/jtreg/vmTestbase/vm/share/process/MessageInput.java
test/hotspot/jtreg/vmTestbase/vm/share/process/MessageOutput.java
test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessExecutor.java
test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessHandler.java
test/hotspot/jtreg/vmTestbase/vm/share/process/StreamListener.java
test/hotspot/jtreg/vmTestbase/vm/share/process/StreamLogger.java
test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageInput.java
test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageOutput.java
test/hotspot/jtreg/vmTestbase/vm/share/process/StreamReader.java
test/hotspot/jtreg/vmTestbase/vm/share/stack/StackUtils.java
test/hotspot/jtreg/vmTestbase/vm/share/transform/AbstractClassFileTransformer.java
test/hotspot/jtreg/vmTestbase/vm/share/transform/AnnotationAppender.java
test/hotspot/jtreg/vmTestbase/vm/share/transform/TransformingClassLoader.java
test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/Crasher.java
test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/CrasherFactory.java
test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/SignalCrasher.java
test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/UnsafeGCCrasher.java
test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/UnsafeJavaCrasher.java
test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/CompileAndDeoptimize.java
test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/MetaspaceStresser.java
--- a/make/test/JtregNativeHotspot.gmk	Mon Apr 30 20:29:19 2018 -0400
+++ b/make/test/JtregNativeHotspot.gmk	Mon Apr 30 18:10:24 2018 -0700
@@ -48,6 +48,21 @@
 
 BUILD_HOTSPOT_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/hotspot/jtreg
 
+################################################################################
+# Former VM TestBase tests.
+################################################################################
+
+VM_TESTBASE_DIR := $(TOPDIR)/test/hotspot/jtreg/vmTestbase
+
+VM_SHARE_INCLUDES := \
+    -I$(VM_TESTBASE_DIR)/vm/share \
+    -I$(VM_TESTBASE_DIR)/nsk/share/native \
+    -I$(VM_TESTBASE_DIR)/nsk/share/jni
+
+BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES)
+
+################################################################################
+
 # Platform specific setup
 ifneq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
   BUILD_HOTSPOT_JTREG_EXCLUDE += liboverflow.c exeThreadSignalMask.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/ExecDriver.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+/**
+ * Starts a new process to execute a command.
+ * <p>Usage: --java|--cmd|--launcher <arg>+
+ * <p>If {@code --cmd} flag is specified, the arguments are treated as
+ * a program to run and its arguments. Non-zero exit code of the created process
+ * will be reported as an {@link AssertionError}.
+ * <p>If {@code --java} flag is specified, the arguments are passed to {@code java}
+ * from JDK under test. If exit code doesn't equal to 0 or 95, {@link AssertionError}
+ * will be thrown.
+ * <p>If {@code --launcher} flag is specified, the arguments treated similar as
+ * for {@code --cmd}, but the started process will have the directory which
+ * contains {@code jvm.so} in dynamic library path, and {@code test.class.path}
+ * as CLASSPATH environment variable. Exit codes are checked as in
+ * {@code --java}, i.e. 0 or 95 means pass.
+ */
+public class ExecDriver {
+    public static void main(String[] args) throws IOException, InterruptedException {
+        boolean java = false;
+        boolean launcher = false;
+
+        String type = args[0];
+        switch (type) {
+            case "--java":
+                String[] oldArgs = args;
+                int count;
+                String libraryPath = System.getProperty("test.nativepath");
+                if (libraryPath != null && !libraryPath.isEmpty()) {
+                    count = 4;
+                    args = new String[args.length + 3];
+                    args[3] = "-Djava.library.path=" + libraryPath;
+                } else {
+                    count = 3;
+                    args = new String[args.length + 2];
+                }
+                args[0] = javaBin();
+                args[1] = "-cp";
+                args[2] = Utils.TEST_CLASS_PATH;
+                System.arraycopy(oldArgs, 1, args, count, oldArgs.length - 1);
+                java = true;
+                break;
+            case "--launcher":
+                java = true;
+                launcher = true;
+            case "--cmd":
+                args = Arrays.copyOfRange(args, 1, args.length);
+                break;
+            default:
+                throw new Error("unknown type: " + type);
+        }
+        // adding 'test.vm.opts' and 'test.java.opts'
+        if (java) {
+            String[] oldArgs = args;
+            String[] testJavaOpts = Utils.getTestJavaOpts();
+            if (testJavaOpts.length > 0) {
+                args = new String[args.length + testJavaOpts.length];
+                // bin/java goes before options
+                args[0] = oldArgs[0];
+                // then external java options
+                System.arraycopy(testJavaOpts, 0, args, 1, testJavaOpts.length);
+                // and then options and args from a test
+                System.arraycopy(oldArgs, 1, args, 1 + testJavaOpts.length, oldArgs.length - 1);
+            }
+        }
+        String command = Arrays.toString(args);
+        System.out.println("exec " + command);
+
+        ProcessBuilder pb = new ProcessBuilder(args);
+        // adding jvm.so to library path
+        if (launcher) {
+            Path dir = Paths.get(Utils.TEST_JDK);
+            String name;
+            if (Platform.isWindows()) {
+                dir = dir.resolve("bin")
+                         .resolve(variant())
+                         .toAbsolutePath();
+                name = "PATH";
+            } else {
+                dir = dir.resolve("lib")
+                         .resolve(variant())
+                         .toAbsolutePath();
+                name = Platform.isOSX() ? "DYLD_LIBRARY_PATH" : "LD_LIBRARY_PATH";
+            }
+
+            System.out.println("  with " + name + " = " +
+                    pb.environment()
+                      .merge(name, dir.toString(), (x, y) -> y + File.pathSeparator + x));
+            System.out.println("  with CLASSPATH = " +
+                    pb.environment()
+                      .put("CLASSPATH", Utils.TEST_CLASS_PATH));
+        }
+        Process p = pb.start();
+        // inheritIO does not work as expected for @run driver
+        new Thread(() -> copy(p.getInputStream(), System.out)).start();
+        new Thread(() -> copy(p.getErrorStream(), System.out)).start();
+        int exitCode = p.waitFor();
+
+        if (exitCode != 0 && (!java || exitCode != 95)) {
+            throw new AssertionError(command + " exit code is " + exitCode);
+        }
+    }
+
+    private static String variant() {
+        if (Platform.isServer()) {
+            return "server";
+        } else if (Platform.isClient()) {
+            return "client";
+        } else if (Platform.isMinimal()) {
+            return "minimal";
+        } else {
+            throw new Error("TESTBUG: unsuppported vm variant");
+        }
+    }
+
+
+    private static void copy(InputStream is, OutputStream os) {
+        byte[] buffer = new byte[1024];
+        int n;
+        try (InputStream close = is) {
+            while ((n = is.read(buffer)) != -1) {
+                os.write(buffer, 0, n);
+            }
+            os.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static String javaBin() {
+        return Paths.get(Utils.TEST_JDK)
+                    .resolve("bin")
+                    .resolve("java")
+                    .toAbsolutePath()
+                    .toString();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/PropertyResolvingWrapper.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * Replaces all {@code ${<X>}} with value of corresponding property({@code X}),
+ * resulting string is handled similarly to {@code @run main} in jtreg.
+ * In other words, {@code main} of first token will be executed with the rest
+ * tokens as arguments.
+ *
+ * If one of properties can't be resolved, {@link Error} will be thrown.
+ */
+public class PropertyResolvingWrapper {
+    private static final Properties properties;
+    static {
+        Properties p = System.getProperties();
+        String name = p.getProperty("os.name");
+        String arch = p.getProperty("os.arch");
+        String family;
+        String simple_arch;
+
+        // copy from jtreg/src/share/classes/com/sun/javatest/regtest/config/OS.java
+        if (name.startsWith("AIX"))
+            family = "aix";
+        else if (name.startsWith("Linux"))
+            family = "linux";
+        else if (name.startsWith("Mac") || name.startsWith("Darwin"))
+            family = "mac";
+        else if (name.startsWith("OS400") || name.startsWith("OS/400") )
+            family = "os400";
+        else if (name.startsWith("SunOS") || name.startsWith("Solaris"))
+            family = "solaris";
+        else if (name.startsWith("Windows"))
+            family = "windows";
+        else
+            family = name.replaceFirst("^([^ ]+).*", "$1"); // use first word of name
+
+        if (arch.contains("64")
+                 && !arch.equals("ia64")
+                 && !arch.equals("ppc64")
+                 && !arch.equals("ppc64le")
+                 && !arch.equals("zArch_64")
+                 && !arch.equals("aarch64"))
+             simple_arch = "x64";
+        else if (arch.contains("86"))
+            simple_arch = "i586";
+        else if (arch.equals("ppc") || arch.equals("powerpc"))
+            simple_arch = "ppc";
+        else if (arch.equals("s390x") || arch.equals("zArch_64"))
+            simple_arch = "s390x";
+        else
+            simple_arch = arch;
+
+        p.setProperty("os.family", family);
+        p.setProperty("os.simpleArch", simple_arch);
+        properties = p;
+    }
+
+    public static void main(String[] args) throws Throwable {
+        List<String> command = new ArrayList<>(args.length);
+        for (int i = 0; i < args.length; ++i) {
+            StringBuilder arg = new StringBuilder(args[i]);
+            while (i < args.length - 1
+                    && (arg.chars()
+                       .filter(c -> c == '"')
+                       .count() % 2) != 0) {
+                arg.append(" ")
+                   .append(args[++i]);
+            }
+            command.add(eval(arg.toString()));
+        }
+        System.out.println("run " + command);
+        try {
+            Class.forName(command.remove(0))
+                 .getMethod("main", String[].class)
+                 .invoke(null, new Object[]{command.toArray(new String[0])});
+        } catch (InvocationTargetException e) {
+           Throwable t = e.getCause();
+           t = t != null ? t : e;
+           throw t;
+        }
+    }
+
+    private static String eval(String string) {
+        int index;
+        int current = 0;
+        StringBuilder result = new StringBuilder();
+        while (current < string.length() && (index = string.indexOf("${", current)) >= 0) {
+            result.append(string.substring(current, index));
+            int endName = string.indexOf('}', index);
+            current = endName + 1;
+            String name = string.substring(index + 2, endName);
+            String value = properties.getProperty(name);
+            if (value == null) {
+                throw new Error("can't find property " + name);
+            }
+            result.append(value);
+        }
+        if (current < string.length()) {
+            result.append(string.substring(current));
+        }
+        int length = result.length();
+
+        if (length > 1 && result.charAt(0) == '"' && result.charAt(length - 1) == '"') {
+            result.deleteCharAt(length - 1);
+            result.deleteCharAt(0);
+        }
+        return result.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/README.md	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,10 @@
+# VM Testbase landing
+
+This directory serves as a _temporary_ landing place for tests converted from so-called VM testbase.
+Most of these tests have been written a long time ago, don't meet modern coding
+standards, guidelines and are in need of reworking.
+Eventually, all the tests located here should be reworked and moved accordingly to
+regular JTReg test suite directory layout convention, i.e. following the same
+layout as product code as close as possible.
+
+New tests must **not** be added into this directory.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/AbstractGoldChecker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+import java.io.UnsupportedEncodingException;
+
+public abstract class AbstractGoldChecker {
+
+    private final StringBuffer sb = new StringBuffer();
+
+    protected abstract String getGoldenString();
+
+    public void print(boolean b) {
+        sb.append(String.valueOf(b));
+    }
+
+    public void print(byte b) {
+        sb.append(String.valueOf(b));
+    }
+
+    public void print(char c) {
+        sb.append(String.valueOf(c));
+    }
+
+    public void print(int i) {
+        sb.append(String.valueOf(i));
+    }
+
+    public void print(long l) {
+        sb.append(String.valueOf(l));
+    }
+
+    public void print(float f) {
+        sb.append(String.valueOf(f));
+    }
+
+    public void print(double d) {
+        sb.append(String.valueOf(d));
+    }
+
+    public void print(String s) {
+        sb.append(s);
+    }
+
+    public void println() {
+        sb.append('\n');
+    }
+
+    public void println(boolean b) {
+        sb.append(String.valueOf(b));
+        sb.append('\n');
+    }
+
+    public void println(byte b) {
+        sb.append(String.valueOf(b));
+        sb.append('\n');
+    }
+
+    public void println(char c) {
+        sb.append(String.valueOf(c));
+        sb.append('\n');
+    }
+
+    public void println(int i) {
+        sb.append(String.valueOf(i));
+        sb.append('\n');
+    }
+
+    public void println(long l) {
+        sb.append(String.valueOf(l));
+        sb.append('\n');
+    }
+
+    public void println(float f) {
+        sb.append(String.valueOf(f));
+        sb.append('\n');
+    }
+
+    public void println(double d) {
+        sb.append(String.valueOf(d));
+        sb.append('\n');
+    }
+
+    public void println(String s) {
+        sb.append(s);
+        sb.append('\n');
+    }
+
+    public void check() {
+        String testOutput;
+        try {
+            testOutput = new String(sb.toString().getBytes("US-ASCII"), "US-ASCII");
+        } catch (UnsupportedEncodingException e) {
+            throw new TestFailure(e);
+        }
+
+        String goldOutput = getGoldenString();
+        if (!compare(testOutput, goldOutput)) {
+            throw new TestFailure(
+                "Gold comparison failed\n" +
+                "\n" +
+                "Test output:\n" +
+                "============\n" +
+                "\n" +
+                testOutput +
+                "\n" +
+                "------------\n" +
+                "\n" +
+                "Gold output:\n" +
+                "============\n" +
+                "\n" +
+                goldOutput +
+                "\n" +
+                "------------\n" +
+                "\n"
+           );
+        }
+    }
+
+    public boolean compare(String src, String dst) {
+        int i1 = 0;
+        int i2 = 0;
+
+        int src_len = src.length();
+        int dst_len = dst.length();
+
+        while ((i1 < src_len) && (i2 < dst_len)) {
+
+            char c1 = src.charAt(i1++);
+            if ((c1 == '\r') && (i1 < src_len)) {
+                c1 = src.charAt(i1++);
+            }
+
+            char c2 = dst.charAt(i2++);
+            if ((c2 == '\r') && (i2 < dst_len)) {
+                c2 = dst.charAt(i2++);
+            }
+
+            if (c1 != c2) {
+                return false;
+            }
+        }
+        return (i1 == src_len) && (i2 == dst_len);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ArgumentParser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,507 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.*;
+
+import nsk.share.test.StressOptions;
+import nsk.share.test.Stresser;
+
+/**
+ * Parser for JDI test's command-line arguments.
+ * <p>
+ * Test's command line may contain two kind of arguments, namely:
+ * <ul>
+ * <li> options for ArgumentParser
+ * <li> other arguments for the test itself
+ * </ul>
+ * <p>
+ * We call <i>raw arguments</i> the <code>args[]</code> array
+ * passed to the test's method <code>main(String&nbsp;args[])</code>.
+ * ArgumentParser instance initialized with raw arguments serves to parse
+ * these two kinds of arguments. Use <code>ArgumentParser(args[])</code>
+ * constructor, or <code>setRawArguments(args[])</code> method
+ * to initialize a ArgumentParser instance with particular raw arguments.
+ * <p>
+ * Arguments, started with ``<code>-</code>'' symbol are called <i>options</i>.
+ * They are recognized by ArgumentParser and are used by support classes
+ * (such as Log, Binder, etc.).
+ * These options should be specified in the following general form:
+ * <ul>
+ * <li> <code>-option=<i>value</i></code>
+ * </ul>
+ * or
+ * <ul>
+ * <li> <code>-option <i>value</i></code>
+ * </ul>
+ * List of the recognized options with their values may be obtained by
+ * invoking method <code>getOptions()</code> that returnes
+ * a <code>Properties</code> object with options values.
+ * It is not recommended to get options value directly. An appropriate methods
+ * such as <code>verbose()</code>, <code>getArch()</code>, etc. should be used
+ * instead.
+ * Options may appear in the test command line in any order.
+ * <p>
+ * All the other arguments of command line are called <i>test arguments</i>
+ * (or simply <i>arguments</i>). These arguments should be handled by test itself.
+ * Full list of the test arguments in the same order as they appears in the command line
+ * may be obtained by invoking method <code>getArguments()</code>.
+ * <p>
+ * Following is the list of basic options accepted by AgrumentParser:
+ * <ul>
+ * <li> <code>-arch=</code>&lt;<i>${ARCH}</i>&gt; -
+ *   architecture name
+ * <li> <code>-waittime=</code>&lt;<i>minutes</i>&gt; -
+ *   timeout in minutes for waiting events or so
+ * <li> <code>-verbose</code> -
+ *   verbose Log mode (default is quiet)
+ * <li> <code>-trace.time</code> -
+ *   prefix log messages with timestamps (default is no)
+ * </ul>
+ * Also AgrumentParser supports following stress options (see nsk.share.test.StressOptions for details):
+ * <ul>
+ * <li> <code>-stressTime</code>
+ * <li> <code>-stressIterationsFactor</code>
+ * <li> <code>-stressThreadsFactor</code>
+ * <li> <code>-stressDebug</code>
+ * </ul>
+ * <p>
+ * Note, that the tests from the particular subsuites have its own argument handlers
+ * wich accepts additional options. See <code>jpda.DebugeeArgumentHandler</code>,
+ * <code>jdi.ArgumentHandler</code>, <code>jdwp.ArgumentHandler</code>.
+ *
+ * @see #setRawArguments(String[])
+ * @see #getRawArguments()
+ * @see #getArguments()
+ * @see #getOptions()
+ *
+ * @see nsk.share.jpda.DebugeeArgumentHandler
+ * @see nsk.share.jdwp.ArgumentHandler
+ * @see nsk.share.jdi.ArgumentHandler
+ * @see nsk.share.jvmti.ArgumentHandler
+ * @see nsk.share.monitoring.ArgumentHandler
+ */
+public class ArgumentParser {
+
+    /**
+     * Raw array of command-line arguments.
+     *
+     * @see #setRawArguments(String[])
+     * @see #getRawArguments()
+     */
+    protected String rawArguments[] = null;
+
+    /**
+     * Refined arguments -- raw arguments but options.
+     *
+     * @see #options
+     * @see #getArguments()
+     */
+    protected String arguments[] = null;
+
+    /**
+     * Recognized options for ArgumentParser class.
+     *
+     * @see #arguments
+     * @see #getOptions()
+     */
+    protected Properties options = new Properties();
+
+    /**
+     * Make new ArgumentParser object with default values of otions.
+     * This constructor is used only to obtain default values of options.
+     *
+     * @see #setRawArguments(String[])
+     */
+    protected ArgumentParser() {
+        String[] args = new String[0];
+        setRawArguments(args);
+    }
+
+    /**
+     * Keep a copy of raw command-line arguments and parse them;
+     * but throw an exception on parsing error.
+     *
+     * @param  args  Array of the raw command-line arguments.
+     *
+     * @throws  BadOption  If option values are invalid.
+     *
+     * @see #setRawArguments(String[])
+     * @see BadOption
+     */
+    public ArgumentParser(String args[]) {
+        setRawArguments(args);
+    }
+
+    /**
+     * Return a copy of the raw command-line arguments kept by
+     * this ArgumentParser instance.
+     *
+     * @throws  NullPointerException  If raw arguments were not
+     *                                set for this instance.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String[] getRawArguments() {
+        return (String[]) rawArguments.clone();
+    }
+
+    /**
+     * Return given raw command-line argument.
+     *
+     * @param index index of argument
+     * @return value of raw argument
+     */
+    public String getRawArgument(int index) {
+            return rawArguments[index];
+    }
+
+    /**
+     * Return refined array of test arguments (only those of the raw
+     * arguments which are not recognized as options for ArgumentParser).
+     *
+     * <p>Note, that sintax of test arguments was not checked;
+     * while syntax of arguments describing ArgumentParser's options
+     * was checked while raw arguments were set to this ArgumentParser
+     * instance.
+     *
+     * @throws  NullPointerException  If raw arguments were not
+     *                                set for this instance.
+     *
+     * @see #setRawArguments(String[])
+     * @see #getOptions()
+     */
+    public String[] getArguments() {
+        return (String[]) arguments.clone();
+    }
+
+    /**
+     * Return list of recognized otions with their values in the form of
+     * <code>Properties</code> object.
+     * If no options has been recognized, this list will be empty.
+     *
+     * @see #setRawArguments(String[])
+     * @see #getArguments()
+     */
+    public Properties getOptions() {
+        return (Properties) options.clone();
+    }
+
+    /**
+     * Join specified arguments into one line using given quoting
+     * and separator symbols.
+     *
+     * @param args Array of the command-line arguments
+     * @param quote Symbol used to quote each argument
+     * @param separator Symbol used as separator between argumnets
+     * @return Single line with arguments
+     */
+    static public String joinArguments(String args[], String quote, String separator) {
+        if (args.length <= 0) {
+            return "";
+        }
+        String line = quote + args[0] + quote;
+        for (int i = 1; i < args.length; i++) {
+            line += separator + quote + args[i] + quote;
+        }
+        return line;
+    }
+
+    /**
+     * Join specified arguments into one line using given quoting symbol
+     * and space as a separator symbol.
+     *
+     * @param args Array of the command-line arguments
+     * @param quote Symbol used to quote each argument
+     * @return Single line with arguments
+     */
+    static public String joinArguments(String args[], String quote) {
+        return joinArguments(args, quote, " ");
+    }
+
+    /**
+     * Keep a copy of command-line arguments and parse them;
+     * but throw an exception on parsing error.
+     *
+     * @param  args  Array of the raw command-line arguments.
+     *
+     * @throws  BadOption  If an option has invalid value.
+     *
+     * @see #getRawArguments()
+     * @see #getArguments()
+     */
+    public void setRawArguments(String args[]) {
+        this.rawArguments = (String[]) args.clone();
+        parseArguments();
+    }
+
+    /**
+     * Add or replace given option value in options list and in raw arguments list.
+     * Use specified <code>rawPrefix</code> while adding to raw arguments list.
+     *
+     * @see #getRawArguments()
+     * @see #getOptions()
+     */
+    public void setOption(String rawPrefix, String name, String value) {
+        String prefix = rawPrefix + name + "=";
+        String arg = prefix + value;
+
+        options.setProperty(name, value);
+
+        int length = rawArguments.length;
+        boolean found = false;
+        for (int i = 0; i < length; i++) {
+            if (rawArguments[i].startsWith(prefix)) {
+                found = true;
+                rawArguments[i] = arg;
+                break;
+            }
+        }
+
+        if (!found) {
+            String[] newRawArguments = new String[length + 1];
+            for (int i = 0; i < length; i++) {
+                newRawArguments[i] = rawArguments[i];
+            }
+            newRawArguments[length] = arg;
+            rawArguments = newRawArguments;
+        }
+    }
+
+    /**
+     * Return current architecture name from ArgumentParser's
+     * options.
+     *
+     * <p>Note that null string is returning if test argument
+     * <code>-arch</code> has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String getArch() {
+        return options.getProperty("arch");
+    }
+
+    /**
+     * Timeout (in minutes) for test's critical section like:
+     * (a) awaiting for an event, or conversly (b) making sure
+     * that there is no unexpected event.
+     *
+     * <p>By default, <i>2</i> minutes is returned if option
+     * <code>-waittime</code> is not set with command line.
+     *
+     * @see TimeoutHandler
+     */
+    public int getWaitTime() {
+        String val = options.getProperty("waittime", "2");
+        int minutes;
+        try {
+            minutes = Integer.parseInt(val);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not integer value of \"waittime\" argument: " + val);
+        }
+        return minutes;
+    }
+
+    /**
+     * Return boolean value of current Log mode:
+     * <ul>
+     * <li><i>true</i> if Log mode is verbose.
+     * <li><i>false</i> otherwise.
+     *
+     * <p>Note that default Log mode is quiet if test argument
+     * <code>-verbose</code> has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean verbose() {
+        return options.getProperty("verbose") != null;
+    }
+
+    /**
+     * Return boolean value of setting of timestamp for log messages:
+     * <ul>
+     * <li><i>true</i> if Log messages are timestamp'ed.
+     * <li><i>false</i> otherwise.
+     *
+     * <p>Note that by default Log messages won't be timestamp'ed until
+     * <code>-trace.time</code> has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean isTimestamp() {
+        return options.getProperty("trace.time") != null;
+    }
+
+    /**
+     * Return level of printing tracing mesages for debugging purpose.
+     * Level <i>0</i> means no tracing messages at all.
+     *
+     * <p>Note that by default no tracing messages will be printed out
+     * until <code>-trace.level</code> has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public int getTraceLevel() {
+        String value = options.getProperty("trace.level", Integer.toString(Log.TraceLevel.DEFAULT));
+        try {
+            int level = Integer.parseInt(value);
+            return level;
+        } catch (NumberFormatException e) {
+            throw new Failure("Not integer value of -trace.level option: " + value);
+        }
+    }
+
+    /**
+     * Parse arguments from rawArgumnets, extact recognized options,
+     * check legality of options values options and store non-option
+     * arguments.
+     *
+     * @throws  NullPointerException  If raw arguments were not set
+     *                                for this ArgumentParser instance.
+     * @throws  BadOption If Option name is not accepted or
+     *                    option has illegal value.
+     *
+     * @see #setRawArguments(String[])
+     * @see #checkOption(String, String)
+     * @see #checkOptions()
+     */
+    protected void parseArguments() {
+        String selected[] = new String [rawArguments.length];
+        Properties properties = new Properties();
+        int count = 0;
+        for (int i=0; i<rawArguments.length; i++) {
+            String argument = rawArguments[i];
+            if (argument.startsWith("-")) {
+                int pos = argument.indexOf("=", 1);
+                String option, value;
+                if (pos < 0) {
+                    option = argument.substring(1);
+                    if (i + 1 < rawArguments.length && !rawArguments[i + 1].startsWith("-")) {
+                        value = rawArguments[i + 1];
+                        ++i;
+                    } else
+                        value = "";
+                } else {
+                    option = argument.substring(1, pos);
+                    value = argument.substring(pos + 1);
+                }
+                if (!checkOption(option, value)) {
+                    throw new BadOption("Unrecognized command line option: " + argument);
+                }
+                properties.setProperty(option, value);
+            } else {
+                selected[count++] = rawArguments[i];
+            }
+        }
+        // Strip away the dummy tail of the selected[] array:
+        arguments = new String [count];
+        System.arraycopy(selected,0,arguments,0,count);
+        options = properties;
+        checkOptions();
+    }
+
+    public StressOptions getStressOptions() {
+        return new StressOptions(rawArguments);
+    }
+
+    /**
+     * Check if the specified option is allowed and has legal value.
+     * <p>
+     * Derived classes for hadling test arguments in particular sub-suites
+     * override this method to allow to accept sub-suite specific options.
+     * However, they should invoke this method of the base class to enshure
+     * that the basic options will be accepted too.
+     *
+     * @return <i>true</i> if option is allowed and has legel value
+     *         <i>false</I> if option is unknown
+     *
+     * @throws  BadOption  If value of the allowed option is illegal.
+     *
+     * @see #setRawArguments(String[])
+     * @see #parseArguments()
+     */
+    protected boolean checkOption(String option, String value) {
+
+        // accept arguments of nsk.share.test.StressOptions
+        if (StressOptions.isValidStressOption(option))
+            return true;
+
+        // options with any string value
+        if (option.equals("arch")) {
+            return true;
+        }
+
+        // options with positive integer value
+        if (option.equals("waittime")
+            || option.equals("trace.level")) {
+            try {
+                int number = Integer.parseInt(value);
+                if (number < 0) {
+                    throw new BadOption(option + ": value must be a positive integer");
+                }
+            } catch (NumberFormatException e) {
+                throw new BadOption(option + ": value must be an integer");
+            }
+            return true;
+        }
+
+        // options without any value
+        if (option.equals("verbose")
+            || option.equals("vbs")
+            || option.equals("trace.time")) {
+            if (!(value == null || value.length() <= 0)) {
+                throw new BadOption(option + ": no value must be specified");
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check that the value of all options are not inconsistent.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @throws  BadOption  If value of the options are inconsistent
+     *
+     * @see #parseArguments()
+     */
+    protected void checkOptions() {
+        // do nothing
+    }
+
+    /**
+     * Thrown if invalid option or option value is found.
+     */
+    public static class BadOption extends IllegalArgumentException {
+        /**
+         * Explain the reason.
+         *
+         * @param  message   Printing message.
+         */
+        public BadOption(String message) {
+            super(message);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassFileFinder.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.nio.file.Path;
+import java.nio.file.Files;
+import java.util.Arrays;
+
+public class ClassFileFinder {
+    private ClassFileFinder() { }
+    /**
+     * Searches for a classfile for the specified class in the specified
+     * classpath.
+     *
+     * @param name a classname
+     * @param classPath @{link File.pathSeparator} separated directories
+     * @return an absolute path to the found classfile, or null if it cannot be
+     *         found
+     */
+    public static Path findClassFile(String name, String classPath) {
+        return Arrays.stream(classPath.split(File.pathSeparator))
+                     .map(java.nio.file.Paths::get)
+                     .map(p -> p.resolve(name.replace('.', File.separatorChar) + ".class"))
+                     .filter(p -> java.nio.file.Files.exists(p))
+                     .map(Path::toAbsolutePath)
+                     .findAny()
+                     .orElse(null);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *  Warning! Using this component need VM option -XX:-UseGCOverheadLimit
+ *
+ */
+
+package nsk.share;
+
+import java.util.*;
+import nsk.share.gc.gp.*;
+import nsk.share.test.ExecutionController;
+import nsk.share.test.Stresser;
+
+/**
+ * The <code>ClassUnloader</code> class allows to force VM to unload class(es)
+ * using memory stressing technique.
+ *
+ * <p>The method <code>unloadClass()</code> is provided which eats memory
+ * to enforce GC to cleanup the heap. So, if all references to a class
+ * and its loader are canceled, this may result in unloading the class.
+ *
+ * <p>ClassUnloader mainly intends to unload a class which was loaded
+ * with especial <code>ClassUnloader.loadClass()</code> method.
+ * A class is considered unloaded if its class loader is finalized.
+ * If there no finalization of class loader detected for some timeout,
+ * class is considered still loaded and method returns <i>false</i>.
+ *
+ * <p>Such finalization control applies only to a class loaded by
+ * ClassUnloader's <code>loadClass()</code> method. Otherwise, if there
+ * was no such class loaded, <code>unloadClass()</code> doesn't wait
+ * for a timeout and always returns <i>false</i>.
+ *
+ * <p>By default internal class loader of <code>CustomClassLoader</code> class
+ * is used for loading classes. This class loader can load class from .class file
+ * located in the specified directory.
+ * Application may define its own class loader, which may load classes using
+ * any other technique. Such class loader should be derived from base
+ * <code>CustomClassLoader</code> class, and set by <code>setClassLoader()</code>
+ * method.
+ *
+ * @see #setClassLoader(CustomClassLoader)
+ * @see #loadClass(String)
+ * @see #loadClass(String, String)
+ * @see #unloadClass()
+ */
+public class ClassUnloader {
+
+    /**
+     * Class name of default class loader.
+     */
+    public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader";
+
+    /**
+     * Whole amount of time in milliseconds to wait for class loader finalization.
+     */
+    private static final int WAIT_TIMEOUT = 15000;
+
+    /**
+     * Piece of time in milliseconds to wait in a loop for class loader finalization.
+     */
+    private static final int WAIT_DELTA = 1000;
+
+    /**
+     * Has class loader been finalized or not.
+     */
+    volatile boolean finalized = false;
+
+    /**
+     * Current class loader used for loading classes.
+     */
+    private CustomClassLoader customClassLoader = null;
+
+    /**
+     * List of classes loaded with current class loader.
+     */
+    private Vector<Class<?>> classObjects = new Vector<Class<?>>();
+
+    /**
+     * Class object of the first class been loaded with current class loader.
+     * To get the rest loaded classes use <code>getLoadedClass(int)</code>.
+     * The call <code>getLoadedClass()</code> is effectively equivalent to the call
+     * <code>getLoadedClass(0)</code>
+     *
+     * @return class object of the first loaded class.
+     *
+     * @see #getLoadedClass(int)
+     */
+    public Class<?> getLoadedClass() {
+        return classObjects.get(0);
+    }
+
+    /**
+     * Returns class objects at the specified index in the list of classes loaded
+     * with current class loader.
+     *
+     * @return class objects at the specified index.
+     */
+    public Class<?> getLoadedClass(int index) {
+        return classObjects.get(index);
+    }
+
+    /**
+     * Creates new instance of <code>CustomClassLoader</code> class as the current
+     * class loader and clears the list of loaded classes.
+     *
+     * @return created instance of <code>CustomClassLoader</code> class.
+     *
+     * @see #getClassLoader()
+     * @see #setClassLoader(CustomClassLoader)
+     */
+    public CustomClassLoader createClassLoader() {
+        customClassLoader = new CustomClassLoader(this);
+        classObjects.removeAllElements();
+
+        return customClassLoader;
+    }
+
+    /**
+     * Sets new current class loader and clears the list of loaded classes.
+     *
+     * @see #getClassLoader()
+     * @see #createClassLoader()
+     */
+    public void setClassLoader(CustomClassLoader customClassLoader) {
+        this.customClassLoader = customClassLoader;
+        classObjects.removeAllElements();
+        customClassLoader.setClassUnloader(this);
+    }
+
+    /**
+     * Returns current class loader or <i>null</i> if not yet created or set.
+     *
+     * @return class loader object or null.
+     *
+     * @see #createClassLoader()
+     * @see #setClassLoader(CustomClassLoader)
+     */
+    public CustomClassLoader getClassLoader() {
+        return customClassLoader;
+    }
+
+    /**
+     * Loads class for specified class name using current class loader.
+     *
+     * <p>Current class loader should be set and capable to load class using only
+     * given class name. No other information such a location of .class files
+     * is passed to class loader.
+     *
+     * @param className name of class to load
+     *
+     * @throws ClassNotFoundException if no bytecode found for specified class name
+     * @throws Failure if current class loader is not specified;
+     *                 or if class was actually loaded with different class loader
+     *
+     * @see #loadClass(String, String)
+     */
+    public void loadClass(String className) throws ClassNotFoundException {
+
+        if (customClassLoader == null) {
+            throw new Failure("No current class loader defined");
+        }
+
+        Class<?> cls = Class.forName(className, true, customClassLoader);
+
+        // ensure that class was loaded by current class loader
+        if (cls.getClassLoader() != customClassLoader) {
+            throw new Failure("Class was loaded by unexpected class loader: " + cls.getClassLoader());
+        }
+
+        classObjects.add(cls);
+    }
+
+    /**
+     * Loads class from .class file located into specified directory using
+     * current class loader.
+     *
+     * <p>If there is no current class loader, then default class loader
+     * is created using <code>createClassLoader()</code>. Parameter <i>classDir</i>
+     * is passed to class loader using <code>CustomClassLoader.setClassPath()</code>
+     * method before loading class.
+     *
+     * @param className name of class to load
+     * @param classDir path to .class file location
+     *
+     * @throws ClassNotFoundException if no .class file found
+     *          for specified class name
+     * @throws Failure if class was actually loaded with different class loader
+     *
+     * @see #loadClass(String)
+     * @see CustomClassLoader#setClassPath(String)
+     */
+    public void loadClass(String className, String classDir) throws ClassNotFoundException {
+
+        if (customClassLoader == null) {
+            createClassLoader();
+        }
+
+        customClassLoader.setClassPath(classDir);
+        loadClass(className);
+    }
+
+    /**
+     * Forces GC to unload previously loaded classes by cleaning all references
+     * to class loader with its loaded classes and eating memory.
+     *
+     * @return  <i>true</i> if classes unloading has been detected
+             or <i>false</i> otherwise
+     *
+     * @throws  Failure if exception other than OutOfMemoryError
+     *           is thrown while eating memory
+     *
+     * @see #eatMemory()
+     */
+    public boolean unloadClass(ExecutionController stresser) {
+
+        finalized = false;
+
+        // free references to class and class loader to be able for collecting by GC
+        long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT;
+        classObjects.removeAllElements();
+        customClassLoader = null;
+
+        // force class unloading by eating memory pool
+        eatMemory(stresser);
+
+        // give GC chance to run and wait for finalization
+        long timeToFinish = System.currentTimeMillis() + waitTimeout;
+        while (!finalized && System.currentTimeMillis() < timeToFinish) {
+            if (!stresser.continueExecution()) {
+                return false;
+            }
+            try {
+                // suspend thread for a while
+                Thread.sleep(WAIT_DELTA);
+            } catch (InterruptedException e) {
+                throw new Failure("Unexpected InterruptedException while class unloading: " + e);
+            }
+        }
+
+        // force GC to unload marked class loader and its classes
+        if (finalized) {
+            Runtime.getRuntime().gc();
+            return true;
+        }
+
+        // class loader has not been finalized
+        return false;
+    }
+
+    public boolean unloadClass() {
+        Stresser stresser = new Stresser() {
+
+            @Override
+            public boolean continueExecution() {
+                return true;
+            }
+
+        };
+        return unloadClass(stresser);
+    }
+
+    /**
+     * Stresses memory by allocating arrays of bytes.
+     *
+     * Note that this method can throw Failure if any exception
+     * is thrown while eating memory. To avoid OOM while allocating
+     * exception we preallocate it before the lunch starts. It means
+     * that exception stack trace does not correspond to the place
+     * where exception is thrown, but points at start of the method.
+     *
+     * @throws  Failure if exception other than OutOfMemoryError
+     *           is thrown while eating memory
+     */
+    public static void eatMemory(ExecutionController stresser) {
+        GarbageUtils.eatMemory(stresser, 50, 1024, 2);
+
+        /*
+         * System.runFinalization() may potentially fail with OOM. This is why
+         * System.runFinalization() is repeated several times.
+         */
+        for (int i = 0; i < 10; ++i) {
+            try {
+                if(!stresser.continueExecution()) {
+                    return;
+                }
+                System.runFinalization();
+                break;
+            } catch (OutOfMemoryError e) {
+            }
+        }
+    }
+
+        /**
+     * Stresses memory by allocating arrays of bytes.
+     *
+     * Note that this method can throw Failure if any exception
+     * is thrown while eating memory. To avoid OOM while allocating
+     * exception we preallocate it before the lunch starts. It means
+     * that exception stack trace does not correspond to the place
+     * where exception is thrown, but points at start of the method.
+     *
+     * @throws  Failure if exception other than OutOfMemoryError
+     *           is thrown while eating memory
+     */
+    public static void eatMemory() {
+        Stresser stresser = new Stresser() {
+
+            @Override
+            public boolean continueExecution() {
+                return true;
+            }
+
+        };
+        GarbageUtils.eatMemory(stresser, 50, 1024, 2);
+        /*
+         * System.runFinalization() may potentially fail with OOM. This is why
+         * System.runFinalization() is repeated several times.
+         */
+        for (int i = 0; i < 10; ++i) {
+            try {
+                if(!stresser.continueExecution()) {
+                    return;
+                }
+                System.runFinalization();
+                break;
+            } catch (OutOfMemoryError e) {
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Consts.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * This class defines constants
+ *
+ */
+public class Consts {
+
+    /**
+     * Exit code when test passed
+     */
+    public final static int TEST_PASSED = 0;
+
+    /**
+     * Exit code when test failed
+     */
+    public final static int TEST_FAILED = 2;
+
+    /**
+     * Shift of exit code
+     */
+    public final static int JCK_STATUS_BASE = 95;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/CustomClassLoader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.*;
+
+/**
+ * The <code>CustomClassLoader</code> class is used in <code>ClassUnloader</code>.
+ *
+ * <p>This class loader can load classes and notify <code>ClassUnloader</code>
+ * about own finalization to make sure that all loaded classes have been unloaded.
+ *
+ * <p>By default this class loader loads class from .class file located in directory
+ * specified with <code>setClassPath()</code> method. To use any other technique
+ * of class loading one should implement derived class, which would override
+ * <code>findClass</code> method.
+ *
+ * @see nsk.share.ClassUnloader
+ *
+ * @see #setClassPath(String)
+ * @see #findClass(String)
+ */
+public class CustomClassLoader extends ClassLoader {
+
+    private ClassUnloader classUnloader;
+    protected String classPath;
+
+    /**
+     * Initializes a newly created <code>CustomClassloader</code> object
+     * not yet linked with any <code>ClassUnloader</code> object.
+     *
+     */
+    public CustomClassLoader() {
+        super(CustomClassLoader.class.getClassLoader());
+        this.classUnloader = null;
+    }
+
+    /**
+     * Initializes a newly created <code>CustomClassloader</code> object
+     * linked with specified <code>ClassUnloader</code> object.
+     *
+     * @param classUnloader an instance of <code>ClassUnloader</code>
+     */
+    public CustomClassLoader(ClassUnloader classUnloader) {
+        super(CustomClassLoader.class.getClassLoader());
+        this.classUnloader = classUnloader;
+    }
+
+    /**
+     * Links this class loader with specified <code>ClassUnloader</code> object.
+     *
+     * @param classUnloader an instance of <code>ClassUnloader</code>
+     */
+    public void setClassUnloader(ClassUnloader classUnloader) {
+        this.classUnloader = classUnloader;
+    }
+
+    /**
+     * Specifies path to .class file location.
+     *
+     * @param classPath a path to .class file location
+     */
+    public void setClassPath(String classPath) {
+        this.classPath = classPath;
+    }
+
+    /**
+     * Finds and loads class for specified class name.
+     * This method loads class from .class file located in a directory
+     * previously specified by <code>setClassPath()</code>.
+     *
+     * @param name The name of the class.
+     *
+     * @throws ClassNotFoundException if no .class file found
+     *          for specified class name
+     *
+     * @see #setClassPath(String)
+     */
+    protected synchronized Class findClass(String name) throws ClassNotFoundException {
+        java.nio.file.Path path = ClassFileFinder.findClassFile(name, classPath);
+        if (path == null) {
+            throw new ClassNotFoundException(name);
+        }
+        String classFileName = path.toString();
+
+        FileInputStream in;
+        try {
+            in = new FileInputStream(classFileName);
+            if (in == null) {
+                throw new ClassNotFoundException(classFileName);
+            }
+        } catch (FileNotFoundException e) {
+            throw new ClassNotFoundException(classFileName, e);
+        }
+
+        int len;
+        byte data[];
+        try {
+            len = in.available();
+            data = new byte[len];
+            for (int total = 0; total < data.length; ) {
+                total += in.read(data, total, data.length - total);
+            }
+        } catch (IOException e) {
+            throw new ClassNotFoundException(classFileName, e);
+        } finally {
+            try {
+                in.close();
+            } catch (IOException e) {
+                throw new ClassNotFoundException(classFileName, e);
+            }
+        }
+
+        return defineClass(name, data, 0, data.length);
+    }
+
+    /**
+     * Notifies <code>ClassUnloader</code> about finalization.
+     */
+    protected void finalize() throws Throwable {
+
+        // notify ClassUnloader about finalization
+        if (classUnloader != null) {
+            classUnloader.finalized = true;
+        }
+
+        super.finalize();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Debug.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class Debug
+{
+    // tests assertion to be valid, otherwise FAIL test with message
+    static public void Assert(boolean condition, String message)
+    {
+        if (!condition)
+            Debug.Fail(message);
+    }
+
+    // print message and FAIL test
+    static public void Fail(String message)
+    {
+        System.out.println(message);
+        System.exit(100);
+    }
+
+    static public void Fail(Throwable e)
+    {
+        Fail(e.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Denotation.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.*;
+
+/**
+ * Denotation implies a pair of algorithms for naming and
+ * indexing of some objects.
+ *
+ * <p>No matter what kind of objects, just make sure that:
+ * <ul>
+ * <li><tt>indexFor(nameFor(index))</tt> equals to <tt>index</tt>
+ * </li>
+ * <li><tt>nameFor(indexFor(name))</tt> is equivalent to <tt>name</tt>
+ * </li>
+ * </ul>
+ *
+ * <p>The notions of indeces equality and names equivalence
+ * are formalized by the methods <tt>equality()</tt> and
+ * <tt>equivalence()</tt> correspondingly.
+ *
+ * <p>For better understanding of Denotation, you may want to
+ * see the TreeNodesDenotation class as an implementation example.
+ *
+ * @see #equality(int[],int[])
+ * @see #equivalence(String,String)
+ * @see TreeNodesDenotation
+ */
+abstract public class Denotation {
+    /**
+     * Check if the <tt>name</tt> is legal, and return the
+     * numeric index for that object denoted by the given
+     * <tt>name</tt>.
+     *
+     * @throws IllegalArgumentException If the <tt>name</tt>
+     * is illegal.
+     */
+    abstract public int[] indexFor(String name);
+
+    /**
+     * Check if the <tt>index[]</tt> is legal, and return
+     * a symbolic name for the object denoted by the given
+     * <tt>index[]</tt>.
+     *
+     * @throws IllegalArgumentException If the <tt>index[]</tt>
+     * is illegal.
+     */
+    abstract public String nameFor(int[] index);
+
+    /**
+     * Re-call to <tt>nameFor(int[])</tt> with the 1-element
+     * array <tt>{i}</tt> as the <tt>index</tt> argument.
+     *
+     * @see #nameFor(int[])
+     */
+    public String nameFor(int i) {
+        return nameFor(new int[] { i });
+    }
+
+    /**
+     * Re-call to <tt>nameFor(int[])</tt> with the 2-elements
+     * array <tt>{i0,i1}</tt> as the <tt>index</tt> argument.
+     *
+     * @see #nameFor(int[])
+     */
+    public String nameFor(int i0, int i1) {
+        return nameFor(new int[] {i0, i1});
+    }
+
+    /**
+     * Re-call to <tt>nameFor(int[])</tt> with the 3-elements
+     * array <tt>{i0,i1,i2}</tt> as the <tt>index</tt> argument.
+     *
+     * @see #nameFor(int[])
+     */
+    public String nameFor(int i0, int i1, int i2) {
+        return nameFor(new int[] {i0, i1, i2});
+    }
+
+    /**
+     * Indeces equality means equality of objects they denote.
+     *
+     * <p>Indeces <tt>index1[]</tt> and <tt>index2[]</tt> are
+     * equal, if they are equal as <tt>int[]</tt> arrays. But,
+     * there is no index equal to <tt>null</tt>; particularly,
+     * <tt>null</tt> is not equal to itself.
+     *
+     * @see Arrays#equals(int[],int[])
+     */
+    public boolean equality(int[] index1, int[] index2) {
+        if (index1 == null || index2 == null)
+            return false;
+        return Arrays.equals(index1,index2);
+    }
+
+    /**
+     * Names equivalence means equality of objects they denote.
+     *
+     * <p>Strings <tt>name1</tt> and <tt>name2</tt> are equivalent,
+     * if correspondent indeces are equal. There is no <tt>name</tt>
+     * equivalent to <tt>null</tt>; particularly, <tt>null</tt> is
+     * not equivalent to itself.
+     *
+     * @see #equality(int[],int[])
+     */
+    public boolean equivalence(String name1, String name2) {
+        if (name1 == null || name2 == null)
+            return false;
+        return equality(indexFor(name1),indexFor(name2));
+    }
+
+    /**
+     * Dummy constructor.
+     */
+    protected Denotation() {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/DummyClassLoader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * This loader's <tt>findClass()</tt> method is dummy.
+ */
+public class DummyClassLoader extends ClassLoader {
+    /**
+     * Cannot instantiate w/o a parent loader.
+     */
+    protected DummyClassLoader() {
+    }
+
+    /**
+     * Delegate everything to the <tt>parent</tt> loader.
+     */
+    public DummyClassLoader(ClassLoader parent) {
+        super(parent);
+    }
+
+    /**
+     * Do nothing: parent loader must load everything.
+     *
+     * @throws ClassNotFoundException In any case.
+     */
+    public Class findClass(String name) throws ClassNotFoundException {
+        throw new ClassNotFoundException(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Failure.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.*;
+
+/**
+ * Thrown to indicate failure caused by some occasional reason,
+ * which does not indicate a problem in the JVM being tested.
+ */
+public class Failure extends RuntimeException {
+        /** Enwrap another throwable. */
+        public Failure(Throwable throwable) {
+                super(throwable);
+        }
+
+        /** Explain particular failure. */
+        public Failure(String message) {
+                super(message);
+        }
+
+        public Failure(String message, Throwable cause) {
+                super(message, cause);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/FileUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileInputStream;
+
+public class FileUtils {
+        private FileUtils() {
+        }
+
+        /**
+         * Read whole file.
+         *
+         * @param file file
+         * @return contents of file as byte array
+         */
+        public static byte[] readFile(File file) throws IOException {
+                InputStream in = new FileInputStream(file);
+                long countl = file.length();
+                if (countl > Integer.MAX_VALUE)
+                        throw new IOException("File is too huge");
+                int count = (int) countl;
+                byte[] buffer = new byte[count];
+                int n = 0;
+                try {
+                        while (n < count) {
+                                int k = in.read(buffer, n, count - n);
+                                if (k < 0)
+                                        throw new IOException("Unexpected EOF");
+                                n += k;
+                        }
+                } finally {
+                        in.close();
+                }
+                return buffer;
+        }
+
+        /**
+         * Read whole file.
+         *
+         * @param name file name
+         * @return contents of file as byte array
+         */
+        public static byte[] readFile(String name) throws IOException {
+                return readFile(new File(name));
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Finalizable.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * Finalizable interface allows <tt>Finalizer</tt> to perform finalization of an object.
+ * Each object that requires finalization at VM shutdown time should implement this
+ * interface and activate a <tt>Finalizer</tt> hook.
+ *
+ * @see Finalizer
+ */
+public interface Finalizable {
+
+    /**
+     * This method will be invoked by <tt>Finalizer</tt> when virtual mashine
+     * shuts down.
+     *
+     * @throws Throwable if any throwable exception thrown during finalization
+     */
+    public void finalizeAtExit() throws Throwable;
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/FinalizableObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * This class is an simple exalmple of finalizable object, that implements interface
+ * <code>Finalizable</code> and invokes standard <code>finalize()</code> method
+ * as finalization.
+ *
+ * @see Finalizable
+ * @see Finalizer
+ */
+public class FinalizableObject implements Finalizable {
+
+    /**
+     * This method will be invoked by <tt>Finalizer</tt> when virtual mashine
+     * shuts down.
+     * For <code>FinalizableObject</code> this method just invoke
+     * <code>finalize()</code>.
+     *
+     * @throws Throwable if any throwable exception thrown during finalization
+     *
+     * @see Object#finalize()
+     * @see Finalizer
+     */
+    public void finalizeAtExit() throws Throwable {
+        finalize();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Finalizer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.Stack;
+
+/**
+ * Finalizer performs object finalization when virtual mashine shuts down.
+ * Finalizer is a thread that acts as a VM shutdown hook.
+ * This thread will be activated as VM shuts down because of
+ * invocation of <code>exit()</code> or termination. After activation
+ * Finalizer just calls <code>finalizeAtExit()</code> method of the specified object.
+ * The finalizable object should implement interface <code>Finalizable</code>.
+ *
+ * @see Finalizable
+ */
+public class Finalizer {
+
+    /** Finalizer thread to register as a VM shutdown hook. */
+    private static FinalizerThread finalizerThread = null;
+
+    /** An object to finalize. */
+    private Finalizable object;
+
+    /**
+     * Create finalizer for the specified object.
+     */
+    public Finalizer(Finalizable object) {
+        this.object = object;
+    }
+
+    /**
+     * Register finalizer for finalization at VM shutdown.
+     */
+    public void activate() {
+        if (finalizerThread == null) {
+            finalizerThread = new FinalizerThread("FinalizerThread for Finalizable objects");
+            finalizerThread.activate();
+        }
+        finalizerThread.add(object);
+    }
+
+    /**
+     * Unregister finalizer for finalization at VM shutdown.
+     */
+    public void deactivate() {
+        if (finalizerThread == null)
+            return;
+        finalizerThread.remove(object);
+    }
+
+    /**
+     * Static inner thread that is registered as a VM shutdown hook
+     * and performs finalization of all registered finalizable objects.
+     */
+    private static class FinalizerThread extends Thread {
+
+        /** Stack of objects registered for finalization. */
+        private Stack<Object> objects = new Stack<Object>();
+
+        /** Make new instance of FinalizerThread with given thread name. */
+        public FinalizerThread(String threadName) {
+            super(threadName);
+        }
+
+        /**
+         * Push an object to the stack of registered objects.
+         */
+        public void add(Finalizable object) {
+            objects.push(object);
+        }
+
+        /**
+         * Remove an object from the stack of registered objects.
+         */
+        public void remove(Finalizable object) {
+            objects.remove(object);
+        }
+
+        /**
+         * Register finalizer thread as a VM shutdown hook.
+         */
+        public void activate() {
+            Runtime.getRuntime().addShutdownHook( this );
+        }
+
+        /**
+         * Unregister finalizer thread as a VM shutdown hook.
+         */
+        public void deactivate() {
+            Runtime.getRuntime().removeShutdownHook( this );
+        }
+
+        /**
+         * Pop all registered objects from the stack and finalize them.
+         */
+        public void run() {
+            while (!objects.empty()) {
+                Finalizable object = (Finalizable)objects.pop();
+                try {
+                    object.finalizeAtExit();
+                } catch (ThreadDeath e) {
+                    throw e;
+                } catch (Throwable ex) {
+                    ex.printStackTrace();
+                }
+            }
+        }
+
+    } // end of FinalizerThread
+
+} // end of Finalizer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/GoldChecker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+import java.io.*;
+
+public class GoldChecker extends AbstractGoldChecker
+{
+    private final String goldOutput;
+
+    public GoldChecker(String main_class_name) {
+        goldOutput = readGoldStr(main_class_name + ".gold");
+    }
+
+    @Override
+    protected String getGoldenString() {
+        return goldOutput;
+    }
+
+    private String readGoldStr(String gold_file_name) {
+        RandomAccessFile f;
+
+        try {
+            f = new RandomAccessFile(gold_file_name, "r");
+        } catch (FileNotFoundException e) {
+            throw new TestBug("Unable to open golden file '" + gold_file_name + "' for reading");
+        }
+
+        byte[] data;
+
+        try {
+            int len = (int)f.length();
+            data = new byte[len];
+            f.read(data);
+        } catch (IOException e) {
+            throw new TestBug("Error reading from golden file'" + gold_file_name + "'");
+        }
+
+        try {
+            f.close();
+        } catch (IOException e) {
+        }
+
+        try {
+            return new String(data, "US-ASCII");
+        } catch (UnsupportedEncodingException e) {
+            throw new TestFailure( e );
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Grep.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ * Emulator of perl's grep function.
+ * This class uses java.util.regexp classes which appear in
+ * JDK1.4 API. This implies the restriction for this class
+ * to not be used with the tests against JDKs prior to 1.4.
+ *
+ * @see java.util.regex.Pattern
+ * @see java.util.regex.Matcher
+ */
+
+public class Grep {
+
+    String[] stringArray;
+    /**
+     * Takes String array as character sequence for matching the pattern.
+     */
+    public Grep (String[] stringArray) {
+        this.stringArray = stringArray;
+    }
+
+    /**
+     * Returns number of non-interleaved occurences of groups which match the pattern.
+     */
+    public int find (String regExpPattern) {
+        if (regExpPattern.length() == 0) {
+            throw new Failure("Empty string as input parameter for Grep.find(regExpPattern) method");
+        }
+        Pattern pattern = Pattern.compile(regExpPattern);
+        int counter = 0;
+        for (int i = 0; i < stringArray.length; i++) {
+
+            String string = stringArray[i];
+            if (string != null) {
+                // Create matcher for this string
+                Matcher matcher = pattern.matcher(string);
+
+                // Find all non-interleaved occurences of pattern in this string
+                for (int ind = 0; ind < string.length(); ) {
+                    if (matcher.find(ind)) {
+                       counter++;
+                       ind = matcher.end();
+                    } else {
+                       break;
+                    }
+                }
+            }
+        }
+        return counter;
+    }
+
+    /**
+     * Returns first string of stringArray with group which matches
+     * the pattern or empty string othrewise.
+     */
+    public String findFirst (String regExpPattern) {
+        if (regExpPattern.length() == 0) {
+            throw new Failure("Empty string as input parameter for Grep.findFirst(regExpPattern) method");
+        }
+        Pattern pattern = Pattern.compile(regExpPattern);
+        String result = "";
+        for (int i = 0; i < stringArray.length; i++) {
+
+            String string = stringArray[i];
+            if (string != null) {
+                // Create matcher for this string
+                Matcher matcher = pattern.matcher(string);
+                if (matcher.find()) {
+                    result = string;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Harakiri.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * Harakiri is used to terminate a stress test with PASS exit status
+ * before the test is terminated as timed out (and so failed).
+ *
+ * <p>Harakiri class holds a thread which sleeps for the given amount
+ * of time, and then wakes up and executes <tt>System.exit()</tt>
+ * with the given exit status. That thread is daemon, so it doesn't
+ * prevent application from exiting once all its threads finish
+ * before it's time for harakiri. Appointing harakiri in zero
+ * delay implies immediate <tt>exit()</tt>.
+ *
+ * <p>There is a limitation: you may appoint no more than one harakiri
+ * per application.
+ */
+public class Harakiri {
+    /**
+     * Use specific <tt>appoint()</tt> method to appoint harakiri.
+     *
+     * @see #appoint(int)
+     * @see #appoint(int,int)
+     */
+    protected Harakiri() {}
+
+    /**
+     * One harakiri per application, or <tt>null</tt> (by default).
+     */
+    private static Thread harakiri = null;
+
+    /**
+     * <p>Return timeout (or waittime) value munus the margin
+     * value (which is assumed 1 minute by default).
+     *
+     * <p>Treat <tt>args[0]</tt> as <tt>$TIMEOUT</tt> value, or seek for
+     * <tt>-waittime=$WAITTIME</tt> value. If both parameters
+     * (or either none of them) are assigned, throw an exception to
+     * report parameters inconsistency.
+     *
+     * <p>Also, seek for <tt>-margin=...</tt> assignment, or assume margin
+     * is 1 minute.
+     *
+     * @param args Is usually obtained via the application's command-line.
+     *
+     * @throws IllegalArgumentException If <tt>args[]</tt> is inconsistent.
+     *
+     * @see #appoint(int)
+     * @see #appoint(int,int)
+     */
+    public static int parseAppointment(String args[]) {
+        int timeout=-1, margin=1;
+        int timeouts=0, waittimes=0, margins=0;
+        for (int i=0; i<args.length; i++) {
+            if (args[i].startsWith("-")) {
+                if (args[i].startsWith("-waittime=")) {
+                    timeout = Integer.parseInt(args[i].substring(10));
+                    waittimes++;
+                }
+                if (args[i].startsWith("-margin=")) {
+                    margin = Integer.parseInt(args[i].substring(8));
+                    margins++;
+                }
+            } else {
+                if (i == 0) {
+                    timeout = Integer.parseInt(args[i]);
+                    timeouts++;
+                }
+            }
+        };
+        if (timeouts==0 && waittimes==0)
+            throw new IllegalArgumentException(
+                "no $TIMEOUT, nor -waittime=$WAITTIME is set");
+        if (waittimes > 1)
+            throw new IllegalArgumentException(
+                "more than one -waittime=... is set");
+        if (margins > 1)
+            throw new IllegalArgumentException(
+                "more than one -margin=... is set");
+
+        int result = timeout - margin;
+        if (result <= 0)
+            throw new IllegalArgumentException(
+                "delay appointment must be greater than "+margin+" minutes");
+        return result;
+    }
+
+    /**
+     * Appoint harakiri after the given amount of <tt>minutes</tt>,
+     * so that exit status would be 95 (to simulate JCK-like PASS
+     * status).
+     *
+     * @throws IllegalStateException If harakiri is already appointed.
+     *
+     * @see #appoint(int,int)
+     * @see #parseAppointment(String[])
+     */
+    public static void appoint(int minutes) {
+        appoint(minutes,95); // JCK-like PASS status
+    }
+
+    /**
+     * Appoint Harakiri for the given amount of <tt>minutes</tt>,
+     * so that the given <tt>status</tt> would be exited when time
+     * is over.
+     *
+     * @throws IllegalStateException If harakiri is already appointed.
+     *
+     * @see #appoint(int)
+     * @see #parseAppointment(String[])
+     */
+    public static void appoint(int minutes, int status) {
+        if (harakiri != null)
+            throw new IllegalStateException("Harakiri is already appointed.");
+
+        final long timeToExit = System.currentTimeMillis() + 60*1000L*minutes;
+        final int  exitStatus = status;
+
+        harakiri = new Thread(Harakiri.class.getName()) {
+            public void run() {
+                long timeToSleep = timeToExit - System.currentTimeMillis();
+                if (timeToSleep > 0)
+                    try {
+                        //
+                        // Use wait() instead of sleep(), because Java 2
+                        // specification doesn't guarantee the method
+                        // sleep() to yield to other threads.
+                        //
+                        Object someDummyObject = new Object();
+                        synchronized (someDummyObject) {
+                            someDummyObject.wait(timeToSleep);
+                        }
+                    } catch (InterruptedException exception) {
+                        exception.printStackTrace(System.err);
+                       //
+                       // OOPS, the dagger for harakiri looks broken:
+                       //
+                       return;
+                    };
+                //
+                // OK, lets do it now:
+                //
+                System.err.println(
+                    "#\n# Harakiri: prescheduled program termination.\n#");
+                System.exit(exitStatus); // harakiri to all threads
+            }
+        };
+
+        harakiri.setPriority(Thread.MAX_PRIORITY);
+        harakiri.setDaemon(true);
+        harakiri.start();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.*;
+
+/**
+ * This class implements a thread transfering bytes from
+ * a given InputStream to a given OutputStream.
+ */
+public class IORedirector extends Thread {
+    private BufferedReader bin  = null;
+    private PrintStream    pout = null;
+    private Log            log  = null;
+
+    /**
+     * Few symbols to precede every text line being redirected.
+     */
+    private String prefix = "";
+
+    /**
+     * Input and output streams must be specified.
+     */
+    private IORedirector() {
+        super("IORedirector");
+    }
+
+    /**
+     * Redirect <code>in</code> to <code>out</code>.
+     *
+     * @deprecated Use newer constructor.
+     *
+     * @see #IORedirector(BufferedReader,Log,String)
+     */
+    public IORedirector(InputStream in, OutputStream out) {
+        this();
+        bin  = new BufferedReader(new InputStreamReader(in));
+        pout = new PrintStream(out);
+    }
+
+    /**
+     * Redirect <code>in</code> to <code>log</code>; and assign
+     * few <code>prefix</code> symbols to precede each text line
+     * being redirected.
+     */
+    public IORedirector(BufferedReader in, Log log, String prefix) {
+        this();
+        this.prefix = prefix;
+        this.bin  = in;
+        this.log = log;
+    }
+
+    /**
+     * Set the prefix for redirected messages;
+     */
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    private boolean cancelled = false;
+    private boolean stopped = false;
+    private boolean started = false;
+
+    /**
+     * Signal to <code>run()</code> method that it should terminate,
+     * and wait until it is finished.
+     */
+    public void cancel () {
+        cancelled = true;
+        while (this.isAlive())
+            try {
+                this.join();
+            } catch (InterruptedException ie) {
+                throw new Failure(ie);
+            };
+        // stopped==true here.
+    }
+
+    /**
+     * Pass data bytes from <code>in</code> to <code>out</code> stream
+     * until EOF is read, or this IORedirector is cancelled.
+     */
+    public void run () {
+        started = true;
+        String logPrefix = "IORedirector-" + prefix;
+        if (bin == null || (pout == null && log == null))
+            return;
+        try {
+            while (!cancelled) {
+                String line = bin.readLine();
+                if (line == null)
+                    break; //EOF
+                String message = prefix + line;
+                if (log != null) {
+                    // It's synchronized and auto-flushed:
+                    log.println(message);
+                } else if (pout != null) {
+                    synchronized (pout) {
+                        pout.println(message);
+                        pout.flush();
+                    }
+                }
+            }
+        } catch (IOException e) {
+            // e.printStackTrace(log.getOutStream());
+            String msg = "# WARNING: Caught IOException while redirecting output stream:\n\t" + e;
+            if (log != null) {
+                log.println(msg);
+            } else if (pout != null) {
+                synchronized (pout) {
+                    pout.println(msg);
+                    pout.flush();
+                }
+            } else {
+                System.err.println(msg);
+                System.err.flush();
+            }
+        };
+        stopped = true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jvmdi.h"
+#include "JVMDITools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char const *TranslateEvent(jint kind) {
+    switch (kind) {
+    case JVMDI_EVENT_SINGLE_STEP:
+        return ("JVMDI_EVENT_SINGLE_STEP");
+    case JVMDI_EVENT_BREAKPOINT:
+        return ("JVMDI_EVENT_BREAKPOINT");
+    case JVMDI_EVENT_FRAME_POP:
+        return ("JVMDI_EVENT_FRAME_POP");
+    case JVMDI_EVENT_EXCEPTION:
+        return ("JVMDI_EVENT_EXCEPTION");
+    case JVMDI_EVENT_USER_DEFINED:
+        return ("JVMDI_EVENT_USER_DEFINED");
+    case JVMDI_EVENT_THREAD_START:
+        return ("JVMDI_EVENT_THREAD_START");
+    case JVMDI_EVENT_THREAD_END:
+        return ("JVMDI_EVENT_THREAD_END");
+    case JVMDI_EVENT_CLASS_PREPARE:
+        return ("JVMDI_EVENT_CLASS_PREPARE");
+    case JVMDI_EVENT_CLASS_UNLOAD:
+        return ("JVMDI_EVENT_CLASS_UNLOAD");
+    case JVMDI_EVENT_CLASS_LOAD:
+        return ("JVMDI_EVENT_CLASS_LOAD");
+    case JVMDI_EVENT_FIELD_ACCESS:
+        return ("JVMDI_EVENT_FIELD_ACCESS");
+    case JVMDI_EVENT_FIELD_MODIFICATION:
+        return ("JVMDI_EVENT_FIELD_MODIFICATION");
+    case JVMDI_EVENT_EXCEPTION_CATCH:
+        return ("JVMDI_EVENT_EXCEPTION_CATCH");
+    case JVMDI_EVENT_METHOD_ENTRY:
+        return ("JVMDI_EVENT_METHOD_ENTRY");
+    case JVMDI_EVENT_METHOD_EXIT:
+        return ("JVMDI_EVENT_METHOD_EXIT");
+    case JVMDI_EVENT_VM_INIT:
+        return ("JVMDI_EVENT_VM_INIT");
+    case JVMDI_EVENT_VM_DEATH:
+        return ("JVMDI_EVENT_VM_DEATH");
+    default:
+        return ("<Unknown Event>");
+    }
+}
+
+char const *TranslateError(jvmdiError err) {
+    switch (err) {
+    case JVMDI_ERROR_NONE:
+        return ("JVMDI_ERROR_NONE");
+    case JVMDI_ERROR_OUT_OF_MEMORY:
+        return ("JVMDI_ERROR_OUT_OF_MEMORY");
+    case JVMDI_ERROR_ACCESS_DENIED:
+        return ("JVMDI_ERROR_ACCESS_DENIED");
+    case JVMDI_ERROR_UNATTACHED_THREAD:
+        return ("JVMDI_ERROR_UNATTACHED_THREAD");
+    case JVMDI_ERROR_VM_DEAD:
+        return ("JVMDI_ERROR_VM_DEAD");
+    case JVMDI_ERROR_INTERNAL:
+        return ("JVMDI_ERROR_INTERNAL");
+    case JVMDI_ERROR_INVALID_THREAD:
+        return ("JVMDI_ERROR_INVALID_THREAD");
+    case JVMDI_ERROR_INVALID_FIELDID:
+        return ("JVMDI_ERROR_INVALID_FIELDID");
+    case JVMDI_ERROR_INVALID_METHODID:
+        return ("JVMDI_ERROR_INVALID_METHODID");
+    case JVMDI_ERROR_INVALID_LOCATION:
+        return ("JVMDI_ERROR_INVALID_LOCATION");
+    case JVMDI_ERROR_INVALID_FRAMEID:
+        return ("JVMDI_ERROR_INVALID_FRAMEID");
+    case JVMDI_ERROR_NO_MORE_FRAMES:
+        return ("JVMDI_ERROR_NO_MORE_FRAMES");
+    case JVMDI_ERROR_OPAQUE_FRAME:
+        return ("JVMDI_ERROR_OPAQUE_FRAME");
+    case JVMDI_ERROR_NOT_CURRENT_FRAME:
+        return ("JVMDI_ERROR_NOT_CURRENT_FRAME");
+    case JVMDI_ERROR_TYPE_MISMATCH:
+        return ("JVMDI_ERROR_TYPE_MISMATCH");
+    case JVMDI_ERROR_INVALID_SLOT:
+        return ("JVMDI_ERROR_INVALID_SLOT");
+    case JVMDI_ERROR_DUPLICATE:
+        return ("JVMDI_ERROR_DUPLICATE");
+    case JVMDI_ERROR_THREAD_NOT_SUSPENDED:
+        return ("JVMDI_ERROR_THREAD_NOT_SUSPENDED");
+    case JVMDI_ERROR_THREAD_SUSPENDED:
+        return ("JVMDI_ERROR_THREAD_SUSPENDED");
+    case JVMDI_ERROR_INVALID_OBJECT:
+        return ("JVMDI_ERROR_INVALID_OBJECT");
+    case JVMDI_ERROR_INVALID_CLASS:
+        return ("JVMDI_ERROR_INVALID_CLASS");
+    case JVMDI_ERROR_CLASS_NOT_PREPARED:
+        return ("JVMDI_ERROR_CLASS_NOT_PREPARED");
+    case JVMDI_ERROR_NULL_POINTER:
+        return ("JVMDI_ERROR_NULL_POINTER");
+    case JVMDI_ERROR_ABSENT_INFORMATION:
+        return ("JVMDI_ERROR_ABSENT_INFORMATION");
+    case JVMDI_ERROR_INVALID_EVENT_TYPE:
+        return ("JVMDI_ERROR_INVALID_EVENT_TYPE");
+    case JVMDI_ERROR_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_INVALID_THREAD_GROUP:
+        return ("JVMDI_ERROR_INVALID_THREAD_GROUP");
+    case JVMDI_ERROR_INVALID_PRIORITY:
+        return ("JVMDI_ERROR_INVALID_PRIORITY");
+    case JVMDI_ERROR_NOT_FOUND:
+        return ("JVMDI_ERROR_NOT_FOUND");
+    case JVMDI_ERROR_INVALID_MONITOR:
+        return ("JVMDI_ERROR_INVALID_MONITOR");
+    case JVMDI_ERROR_ILLEGAL_ARGUMENT:
+        return ("JVMDI_ERROR_ILLEGAL_ARGUMENT");
+    case JVMDI_ERROR_NOT_MONITOR_OWNER:
+        return ("JVMDI_ERROR_NOT_MONITOR_OWNER");
+    case JVMDI_ERROR_INTERRUPT:
+        return ("JVMDI_ERROR_INTERRUPT");
+    case JVMDI_ERROR_INVALID_TYPESTATE:
+        return ("JVMDI_ERROR_INVALID_TYPESTATE");
+    case JVMDI_ERROR_INVALID_CLASS_FORMAT:
+        return ("JVMDI_ERROR_INVALID_CLASS_FORMAT");
+    case JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION:
+        return ("JVMDI_ERROR_CIRCULAR_CLASS_DEFINITION");
+    case JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_ADD_METHOD_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_SCHEMA_CHANGE_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_FAILS_VERIFICATION:
+        return ("JVMDI_ERROR_FAILS_VERIFICATION");
+#ifdef JVMDI_VERSION_1_2
+    case JVMDI_ERROR_UNSUPPORTED_VERSION:
+        return ("JVMDI_ERROR_UNSUPPORTED_VERSION");
+    case JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_HIERARCHY_CHANGE_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_DELETE_METHOD_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_NAMES_DONT_MATCH:
+        return ("JVMDI_ERROR_NAMES_DONT_MATCH");
+    case JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED");
+    case JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED:
+        return ("JVMDI_ERROR_METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED");
+#endif
+    default:
+        return ("<Unknown Error>");
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/JVMDITools.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char const *TranslateEvent(jint kind);
+char const *TranslateError(jvmdiError err);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/JVMTIagent.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,1276 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ *
+ * JVMTI agent used for run every test from the testbase in a special
+ * debug mode. This mode is intended to be part of serviceability
+ * reliability testing.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <jvmti.h>
+
+#include "nsk_tools.h"
+#include "jni_tools.h"
+#include "JVMTITools.h"
+#include "jvmti_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static jvmtiEnv *jvmti = NULL; /* JVMTI env */
+static jvmtiEventCallbacks callbacks;
+static jrawMonitorID eventLock; /* raw monitor used for exclusive ownership of HotSwap function */
+
+static volatile int debug_mode = 0; /* 0 - verbose mode off;
+                                       1 - verbose mode on;
+                                       2 - verbose mode on including all JVMTI events reporting,
+                                           produces a huge number of messages */
+
+/* stress level */
+static volatile int stress_lev = 0; /* 0 - default mode: generation of all events except
+                                                ExceptionCatch,
+                                                MethodEntry/Exit, SingleStep;
+                                       1 - generation of all events except
+                                                MethodEntry/Exit,
+                                                SingleStep;
+                                       2 - generation of all events except
+                                                SingleStep;
+                                       3 - generation of all events, including
+                                                ExceptionCatch,
+                                                MethodEntry/Exit,
+                                                SingleStep
+                                     */
+
+#define TRUE 1
+#define FALSE 0
+
+/**** the following is used for "postVM_DEATH" events watching ****/
+static volatile int vm_death_occured = FALSE;
+/************************************************/
+
+/**** the following is used for HotSwap mode ****/
+
+/* HotSwap modes:
+ HOTSWAP_OFF                - default mode: HotSwap off;
+ HOTSWAP_EVERY_METHOD_ENTRY - HotSwap tested class in every method entry event
+                              of running test
+ HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS - HotSwap tested class in every
+                              method entry event of every class
+ HOTSWAP_EVERY_SINGLE_STEP  - HotSwap tested class in every single step event
+                              of running test
+ HOTSWAP_EVERY_EXCEPTION    - HotSwap tested class in every exception event
+                              of running test
+ HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS - HotSwap tested class in every
+                              exception event of every class
+ */
+
+#define HOTSWAP_OFF 0
+#define HOTSWAP_EVERY_METHOD_ENTRY 2
+#define HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS 20
+#define HOTSWAP_EVERY_SINGLE_STEP 3
+#define HOTSWAP_EVERY_EXCEPTION 4
+#define HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS 40
+
+static int hotswap = HOTSWAP_OFF;
+
+typedef struct {   /* test class info */
+    char *clazzsig;  /* class signature */
+    jclass cls;      /* a class to be redefined */
+    jint bCount;     /* number of bytes defining the class */
+    jbyte *clsBytes; /* bytes defining the class */
+    struct class_info *next;
+} class_info;
+
+
+static const char *shortTestName = NULL; /* name of the test without package prefix */
+static jclass rasCls; /* reference to the auxiliary class RASagent used for HotSwap */
+static class_info *clsInfo = NULL, *clsInfoFst = NULL;
+
+static void lock(JNIEnv*);
+static void unlock(JNIEnv*);
+static jint allocClsInfo(JNIEnv*, char*, jclass);
+static void deallocClsInfo(JNIEnv*);
+static int findAndHotSwap(JNIEnv*, jclass);
+static int doHotSwap(JNIEnv*, jclass, jint, jbyte*);
+static void display(int, const char format[], ...);
+static void clearJavaException(JNIEnv*);
+static int enableEventsCaps();
+static int addStressEvents();
+static void getVerdict(JNIEnv*, const char *);
+/************************************************/
+
+/** callback functions **/
+void JNICALL
+Breakpoint(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thr, jmethodID method,
+        jlocation loc) {
+
+    display(1, "#### JVMTIagent: Breakpoint occurred ####\n");
+
+    getVerdict(jni_env, "Breakpoint");
+}
+
+void JNICALL
+ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jclass class_beeing_redefined,
+        jobject loader, const char* name, jobject protection_domain,
+        jint class_data_len, const unsigned char* class_data,
+        jint *new_class_data_len, unsigned char** new_class_data) {
+
+    display(1, "#### JVMTIagent: ClassFileLoadHook occurred ####\n");
+
+    getVerdict(jni_env, "ClassFileLoadHook");
+}
+
+void JNICALL
+ClassLoad(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread, jclass klass) {
+    char *cls_sig;
+    jint clsByteCount;
+
+    display((hotswap != HOTSWAP_OFF)?0:1,
+        "#### JVMTIagent: ClassLoad occurred ####\n");
+
+    getVerdict(jni_env, "ClassLoad");
+
+    if (hotswap != HOTSWAP_OFF) {
+        /* enter into a raw monitor for exclusive work with redefined class */
+        lock(jni_env);
+        display(0, "#### JVMTIagent: ClassLoad: >>>>>>>> entered the raw monitor \"eventLock\" ####\n");
+
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature,
+                jvmti_env, klass, &cls_sig, /*&generic*/NULL)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to get class signature\n");
+        else {
+            if (shortTestName != NULL) {
+                if (strstr((const char*) cls_sig, shortTestName) != NULL) {
+                    display(0, "#### JVMTIagent: found test class matched with \"%s\"\n\
+<JVMTIagent>\tsignature=%s\n",
+                        shortTestName, cls_sig);
+                    clsByteCount = allocClsInfo(jni_env, cls_sig, klass);
+                    display(0, "#### JVMTIagent: %d bytes defining the class have been successfully loaded\n",
+                        clsByteCount);
+                }
+            }
+        }
+
+        /* exit from the raw monitor */
+        unlock(jni_env);
+        display(0, "#### JVMTIagent: ClassLoad: <<<<<<<< exited from the raw monitor \"eventLock\" ####\n\n");
+    }
+}
+
+void JNICALL
+ClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jclass cls) {
+
+    display(1, "#### JVMTIagent: ClassPrepare occurred ####\n");
+
+    getVerdict(jni_env, "ClassPrepare");
+}
+
+void JNICALL
+CompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size,
+        const void* code_addr,  jint map_length,
+        const jvmtiAddrLocationMap* map, const void* compile_info) {
+
+    display(1, "#### JVMTIagent: CompiledMethodLoad occurred ####\n");
+
+    getVerdict(NULL, "CompiledMethodLoad");
+}
+
+void JNICALL
+CompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method,
+        const void* code_addr) {
+
+    display(1, "#### JVMTIagent: CompiledMethodUnload occurred ####\n");
+
+    getVerdict(NULL, "CompiledMethodUnload");
+}
+
+void JNICALL
+DataDumpRequest(jvmtiEnv *jvmti_env) {
+
+    display(1, "#### JVMTIagent: DataDumpRequest occurred ####\n");
+
+    getVerdict(NULL, "DataDumpRequest");
+}
+
+void JNICALL
+DynamicCodeGenerated(jvmtiEnv *jvmti_env,
+        const char* name,
+        const void* address,
+        jint length) {
+
+    display(1, "#### JVMTIagent: DynamicCodeGenerated occurred ####\n");
+
+    getVerdict(NULL, "DynamicCodeGenerated");
+}
+
+void JNICALL
+Exception(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thr,
+        jmethodID method, jlocation location, jobject exception,
+        jmethodID catch_method, jlocation catch_location) {
+    jclass decl_clazz;
+
+    display((hotswap == HOTSWAP_EVERY_EXCEPTION ||
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS)?0:1,
+        "#### JVMTIagent: Exception occurred ####\n");
+
+    getVerdict(jni_env, "Exception");
+
+    if (hotswap == HOTSWAP_EVERY_EXCEPTION ||
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS) {
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass,
+                jvmti_env, method, &decl_clazz)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to get method declaring class\n");
+
+        if (findAndHotSwap(jni_env, decl_clazz) != 0)
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to hotswap class\n");
+    }
+}
+
+void JNICALL
+FieldAccess(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jmethodID method,
+        jlocation location, jclass field_klass, jobject obj, jfieldID field) {
+
+    display(1, "#### JVMTIagent: FieldAccess occurred ####\n");
+
+    getVerdict(jni_env, "FieldAccess");
+}
+
+void JNICALL
+FieldModification(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jmethodID method, jlocation location,
+        jclass field_klass, jobject obj,
+        jfieldID field, char sig, jvalue new_value) {
+
+    display(1, "#### JVMTIagent: FieldModification occurred ####\n");
+
+    getVerdict(jni_env, "FieldModification");
+}
+
+void JNICALL
+FramePop(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jmethodID method, jboolean wasPopedByException) {
+
+    display(1, "#### JVMTIagent: FramePop occurred ####\n");
+
+    getVerdict(jni_env, "FramePop");
+}
+
+void JNICALL
+GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
+
+    display(1, "#### JVMTIagent: GarbageCollectionFinish occurred ####\n");
+
+    getVerdict(NULL, "GarbageCollectionFinish");
+}
+
+void JNICALL
+GarbageCollectionStart(jvmtiEnv *jvmti_env) {
+
+    display(1, "#### JVMTIagent: GarbageCollectionStart occurred ####\n");
+
+    getVerdict(NULL, "GarbageCollectionStart");
+}
+
+void JNICALL
+MonitorContendedEnter(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thr,
+        jobject obj) {
+
+    display(1, "#### JVMTIagent: MonitorContendedEnter occurred ####\n");
+
+    getVerdict(jni_env, "MonitorContendedEnter");
+}
+
+void JNICALL
+MonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thr,
+        jobject obj) {
+
+    display(1, "#### JVMTIagent: MonitorContendedEntered occurred ####\n");
+
+    getVerdict(jni_env, "MonitorContendedEntered");
+}
+
+void JNICALL
+MonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thr, jobject obj,
+        jlong tout) {
+
+    display(1, "#### JVMTIagent: MonitorWait occurred ####\n");
+
+    getVerdict(jni_env, "MonitorWait");
+}
+
+void JNICALL
+MonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env,
+        jthread thr, jobject obj, jboolean timed_out) {
+
+    display(1, "#### JVMTIagent: MonitorWaited occurred ####\n");
+
+    getVerdict(jni_env, "MonitorWaited");
+}
+
+void JNICALL
+NativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
+        jmethodID method, void *addr, void **new_addr) {
+
+    display(1, "#### JVMTIagent: NativeMethodBind occurred ####\n");
+
+    getVerdict(jni_env, "NativeMethodBind");
+}
+
+void JNICALL
+ObjectFree(jvmtiEnv *jvmti_env, jlong tag) {
+
+    display(1, "#### JVMTIagent: ObjectFree occurred ####\n");
+
+    getVerdict(NULL, "ObjectFree");
+}
+
+void JNICALL
+ThreadEnd(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread) {
+
+    display(1, "#### JVMTIagent: ThreadEnd occurred ####\n");
+
+    getVerdict(jni_env, "ThreadEnd");
+}
+
+void JNICALL
+ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread) {
+
+    display(1, "#### JVMTIagent: ThreadStart occurred ####\n");
+
+    getVerdict(jni_env, "ThreadStart");
+}
+
+void JNICALL
+VMDeath(jvmtiEnv *jvmti_env, JNIEnv *jni_env) {
+    vm_death_occured = TRUE;
+
+    display(0, "#### JVMTIagent: VMDeath occurred ####\n");
+
+    if (hotswap != HOTSWAP_OFF) {
+        deallocClsInfo(jni_env);
+        display(0, "#### JVMTIagent: allocated memory was successfully freed ####\n");
+    }
+}
+
+void JNICALL
+VMInit(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thr) {
+
+    display(0, "#### JVMTIagent: VMInit occurred ####\n");
+
+    getVerdict(jni_env, "VMInit");
+}
+
+void JNICALL
+VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env) {
+
+    display(0, "#### JVMTIagent: VMStart occurred ####\n");
+
+    getVerdict(jni_env, "VMStart");
+}
+
+JNIEXPORT void JNICALL
+VMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
+        jobject object, jclass object_klass, jlong size) {
+
+    display(1, "#### JVMTIagent: VMObjectAlloc occurred ####\n");
+
+    getVerdict(jni_env, "VMObjectAlloc");
+}
+
+void JNICALL
+SingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread,
+        jmethodID method, jlocation location) {
+    jclass decl_clazz;
+
+    display((hotswap == HOTSWAP_EVERY_SINGLE_STEP)?0:1,
+        "#### JVMTIagent: SingleStep occurred ####\n");
+
+    getVerdict(jni_env, "SingleStep");
+
+    if (hotswap == HOTSWAP_EVERY_SINGLE_STEP) {
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass,
+                jvmti_env, method, &decl_clazz)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to get method declaring class\n");
+
+        if (findAndHotSwap(jni_env, decl_clazz) != 0)
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to hotswap class\n");
+    }
+}
+
+void JNICALL
+MethodEntry(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jmethodID method) {
+    jclass decl_clazz;
+
+    display((hotswap == HOTSWAP_EVERY_METHOD_ENTRY ||
+            hotswap == HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS)?0:1,
+        "#### JVMTIagent: MethodEntry occurred ####\n");
+
+    getVerdict(jni_env, "MethodEntry");
+
+    if (hotswap == HOTSWAP_EVERY_METHOD_ENTRY ||
+            hotswap == HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS) {
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass,
+                jvmti_env, method, &decl_clazz)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to get method declaring class\n");
+
+        if (findAndHotSwap(jni_env, decl_clazz) != 0)
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to hotswap class\n");
+    }
+}
+
+void JNICALL
+MethodExit(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
+        jthread thr, jmethodID method,
+        jboolean was_poped_by_exc, jvalue return_value) {
+
+    display(1, "#### JVMTIagent: MethodExit occurred ####\n");
+
+    getVerdict(jni_env, "MethodExit");
+}
+
+void JNICALL
+ExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thr,
+        jmethodID method, jlocation location, jobject exception) {
+    jclass decl_clazz;
+
+    display((hotswap == HOTSWAP_EVERY_EXCEPTION ||
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS)?0:1,
+        "#### JVMTIagent: ExceptionCatch occurred ####\n");
+
+    getVerdict(jni_env, "ExceptionCatch");
+
+    if (hotswap == HOTSWAP_EVERY_EXCEPTION ||
+            hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS) {
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(GetMethodDeclaringClass,
+                jvmti_env, method, &decl_clazz)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to get method declaring class\n");
+
+        if (findAndHotSwap(jni_env, decl_clazz) != 0)
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to hotswap class\n");
+    }
+}
+/************************/
+
+static void lock(JNIEnv *jni_env) {
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorEnter,
+            jvmti, eventLock)))
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: failed to enter a raw monitor\n");
+}
+
+static void unlock(JNIEnv *jni_env) {
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(RawMonitorExit,
+            jvmti, eventLock)))
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: failed to exit a raw monitor\n");
+}
+
+JNIEXPORT jint JNICALL
+Java_nsk_share_RASagent_setHotSwapMode(JNIEnv *jni_env, jclass cls,
+        jboolean vrb, jint level, jstring shortName) {
+    jvmtiCapabilities capabil;
+    jmethodID mid = NULL;
+
+    if (jvmti == NULL) {
+        printf("ERROR(%s,%d): JVMTIagent was not properly loaded: JVMTI env = NULL\n",
+               __FILE__, __LINE__);
+        return 1;
+    }
+
+    /* get supported JVMTI capabilities */
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(GetCapabilities,
+            jvmti, &capabil)))
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: failed to get capabilities\n");
+    if (capabil.can_redefine_classes != 1) { /* ???????????? */
+        printf("ERROR: JVMTIagent: Class File Redefinition (HotSwap) is not implemented in this VM\n");
+        return 1;
+    }
+
+    if (vrb == JNI_TRUE && debug_mode == 0)
+        debug_mode = 1;
+
+    hotswap = level;
+    switch (hotswap) {
+        case HOTSWAP_OFF:
+            display(0, "#### JVMTIagent: hotswap mode off ####\n");
+            return 0;
+        case HOTSWAP_EVERY_METHOD_ENTRY:
+            stress_lev = 2;
+            display(0, "#### JVMTIagent: hotswapping class in every method entry event enabled ####\n\
+<JVMTIagent>\tHotSwap stress level: %d\n",
+                stress_lev);
+            break;
+        case HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS:
+            stress_lev = 2;
+            display(0, "#### JVMTIagent: hotswapping class in every method entry event for every class enabled ####\n\
+<JVMTIagent>\tHotSwap stress level: %d\n",
+                stress_lev);
+            break;
+        case HOTSWAP_EVERY_SINGLE_STEP:
+            stress_lev = 3;
+            display(0, "#### JVMTIagent: hotswapping class in every single step event enabled ####\n\
+<JVMTIagent>\tHotSwap stress level: %d\n",
+                stress_lev);
+            break;
+        case HOTSWAP_EVERY_EXCEPTION:
+            stress_lev = 4;
+            display(0, "#### JVMTIagent: hotswapping class in every exception event enabled ####\n\
+<JVMTIagent>\tHotSwap stress level: %d\n",
+                stress_lev);
+            break;
+        case HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS:
+            stress_lev = 40;
+            display(0, "#### JVMTIagent: hotswapping class in every exception event for every class enabled ####\n\
+<JVMTIagent>\tHotSwap stress level: %d\n",
+                stress_lev);
+            break;
+        default:
+            printf("ERROR(%s,%d): JVMTIagent: unknown value of HotSwap stress level: \"%d\"\n",
+                __FILE__,__LINE__,hotswap);
+            return 1;
+    }
+
+    if (!NSK_JNI_VERIFY(jni_env, (shortTestName = NSK_CPP_STUB3(GetStringUTFChars,
+            jni_env, shortName, NULL)) != NULL)) {
+        printf("ERROR: JVMTIagent: unable to get UTF-8 characters of the string\n");
+        return 1;
+    }
+    display(0, "#### JVMTIagent: short name of current test is \"%s\"\n",
+        shortTestName);
+
+    if (!NSK_JNI_VERIFY(jni_env, (rasCls = NSK_CPP_STUB2(NewGlobalRef,
+            jni_env, cls)) != NULL)) {
+        printf("ERROR JVMTIagent: unable to create a new global reference of the class \"RASagent\"\n");
+        return 1;
+    }
+
+    if (addStressEvents() != 0) {
+        printf("ERROR(%s,%d): JVMTIagent terminated abnormally! ####\n",
+            __FILE__,__LINE__);
+        return 1;
+    }
+
+    return 0;
+}
+
+static jint allocClsInfo(JNIEnv *jni_env, char *cls_sig, jclass clazz) {
+    class_info *_clsInfo = NULL;
+    jmethodID mid = NULL;
+    jbyteArray classBytes;
+    jboolean isCopy;
+
+    if ((_clsInfo = (class_info*)
+            malloc(sizeof(class_info))) == NULL)
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: cannot allocate memory for class_info\n");
+
+    /* fill the structure class_info */
+    _clsInfo->clazzsig = cls_sig;
+
+    if (!NSK_JNI_VERIFY(jni_env, ((*_clsInfo).cls = NSK_CPP_STUB2(NewGlobalRef,
+            jni_env, clazz)) != NULL)) {
+        printf("ERROR: JVMTIagent: unable to create a new global reference of class \"%s\"\n",
+            _clsInfo->clazzsig);
+        free(_clsInfo);
+        deallocClsInfo(jni_env);
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: unable to create a new global reference of class\n");
+    }
+
+    if (!NSK_JNI_VERIFY(jni_env, (mid =
+        NSK_CPP_STUB4(GetStaticMethodID, jni_env, rasCls,
+            "loadFromClassFile", "(Ljava/lang/String;)[B")) != NULL))
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: unable to get ID of the method \"loadFromClassFile\"\n");
+
+    classBytes = (jbyteArray) NSK_CPP_STUB4(CallStaticObjectMethod,
+        jni_env, rasCls, mid, NSK_CPP_STUB2(NewStringUTF, jni_env, cls_sig));
+
+    clearJavaException(jni_env);
+
+    (*_clsInfo).bCount = NSK_CPP_STUB2(GetArrayLength, jni_env, classBytes);
+
+    (*_clsInfo).clsBytes =
+        NSK_CPP_STUB3(GetByteArrayElements, jni_env, classBytes, &isCopy);
+
+    _clsInfo->next = NULL;
+
+    if (clsInfo != NULL) {
+        clsInfo->next = (struct class_info*) _clsInfo;
+    }
+    else {
+        clsInfoFst = _clsInfo;
+    }
+    clsInfo = _clsInfo;
+
+    return (*_clsInfo).bCount;
+}
+
+static void deallocClsInfo(JNIEnv *jni_env) {
+    class_info *clsInfoCurr = clsInfoFst;
+
+    NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni_env, rasCls));
+
+    while(clsInfoCurr != NULL) {
+        class_info *_clsInfo = clsInfoCurr;
+
+        if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
+                jvmti, (unsigned char*) clsInfoCurr->clazzsig)))
+            NSK_CPP_STUB2(FatalError, jni_env,
+                "JVMTIagent: failed to deallocate memory for clazzsig\n");
+
+        NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni_env, clsInfoCurr->cls));
+
+        clsInfoCurr = (class_info*) clsInfoCurr->next;
+
+        free(_clsInfo);
+    }
+    /* fix for 4756585: indicate that stucture class_info is empty now */
+    clsInfoFst = NULL;
+}
+
+static int findAndHotSwap(JNIEnv *jni_env, jclass clazz) {
+    int ret_code = 0;
+    char *clazzsig = NULL;
+    class_info *clsInfoCurr = clsInfoFst;
+
+    display(1, "\n#### JVMTIagent: findAndHotSwap: obtaining class signature of class to be hotswap ...\n");
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(GetClassSignature,
+            jvmti, clazz, &clazzsig, /*&generic*/NULL)))
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: findAndHotSwap: failed to get class signature\n");
+    else {
+        display(1, "#### JVMTIagent: findAndHotSwap: ... class signature obtained: \"%s\"\n",
+            clazzsig);
+
+        /* enter into a raw monitor for exclusive work with redefined class */
+        lock(jni_env);
+        display(0, "#### JVMTIagent: findAndHotSwap: >>>>>>>> entered the raw monitor \"eventLock\" ####\n");
+
+        while(clsInfoCurr != NULL) {
+            if (hotswap == HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS ||
+                    hotswap == HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS) {
+                display(1, "\n#### JVMTIagent: findAndHotSwap: going to hotswap tested class \"%s\" during execution of class \"%s\" ...\n",
+                    clsInfoCurr->clazzsig, clazzsig);
+                if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
+                        jvmti, (unsigned char*) clazzsig)))
+                    NSK_CPP_STUB2(FatalError, jni_env,
+                        "JVMTIagent: findAndHotSwap: failed to deallocate memory for clazzsig\n");
+
+                if (doHotSwap(jni_env, clsInfoCurr->cls,
+                        clsInfoCurr->bCount, clsInfoCurr->clsBytes) != 0) {
+                    ret_code = 1;
+                    break;
+                }
+            }
+            else {
+                if (strcmp(clazzsig, clsInfoCurr->clazzsig) == 0) {
+                    display(0, "\n#### JVMTIagent: findAndHotSwap: tested class found \"%s\" ...\n",
+                        clazzsig);
+
+                    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(Deallocate,
+                            jvmti, (unsigned char*) clazzsig)))
+                        NSK_CPP_STUB2(FatalError, jni_env,
+                            "JVMTIagent: findAndHotSwap: failed to deallocate memory for clazzsig\n");
+
+                    display(0, "\n#### JVMTIagent: findAndHotSwap: going to hotswap tested class \"%s\" ...\n",
+                        clsInfoCurr->clazzsig);
+                    if (doHotSwap(jni_env, clsInfoCurr->cls,
+                            clsInfoCurr->bCount, clsInfoCurr->clsBytes) != 0) {
+                        ret_code = 1;
+                        break;
+                    }
+                }
+            }
+
+            clsInfoCurr = (class_info*) clsInfoCurr->next;
+        }
+
+        /* exit raw monitor */
+        unlock(jni_env);
+        display(0, "#### JVMTIagent: findAndHotSwap: <<<<<<<< exited from the raw monitor \"eventLock\" ####\n\n");
+    }
+
+    return ret_code;
+}
+
+static int doHotSwap(JNIEnv *jni_env, jclass redefCls, jint bCount,
+        jbyte *classBytes) {
+    jvmtiClassDefinition classDef;
+
+    /* fill the structure jvmtiClassDefinition */
+    classDef.klass = redefCls;
+    classDef.class_byte_count = bCount;
+    classDef.class_bytes = (unsigned char*) classBytes;
+
+    display(0, "#### JVMTIagent: >>>>>>>> Invoke RedefineClasses():\n\
+<JVMTIagent>\tnew class byte count=%d\n",
+        classDef.class_byte_count);
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(RedefineClasses,
+            jvmti, 1, &classDef)))
+        return 1;
+
+    display(0, "#### JVMTIagent: <<<<<<<< RedefineClasses() is successfully done ####\n");
+
+    return 0;
+}
+
+static int addStressEvents() {
+    static int stepEventSet = JNI_FALSE;
+    static int methodsEventSet = JNI_FALSE;
+    static int excCatchEventSet = JNI_FALSE;
+
+    if (stress_lev >= 3) {
+        /* SingleStep events */
+        if (stepEventSet == JNI_FALSE) { /* don't set the event twice */
+            display(0, "#### JVMTIagent: setting SingleStep events ...\n");
+
+            callbacks.SingleStep = &SingleStep;
+
+            if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+                    jvmti, JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, NULL)))
+                return JNI_ERR;
+
+            stepEventSet = JNI_TRUE;
+
+            display(0, "#### JVMTIagent: ... setting SingleStep events done\n");
+        }
+    }
+
+    if (stress_lev >= 2) {
+        /* MethodEntry/Exit events */
+        if (methodsEventSet == JNI_FALSE) { /* don't set the event twice */
+            display(0, "#### JVMTIagent: setting MethodEntry events ...\n");
+
+            callbacks.MethodEntry = &MethodEntry;
+
+            if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+                    jvmti, JVMTI_ENABLE, JVMTI_EVENT_METHOD_ENTRY, NULL)))
+                return JNI_ERR;
+
+            display(0, "#### JVMTIagent: ... setting MethodEntry events done\n");
+
+            /* MethodExit events */
+            display(0, "#### JVMTIagent: setting MethodExit events ...\n");
+
+            callbacks.MethodExit = &MethodExit;
+
+            if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+                    jvmti, JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, NULL)))
+                return JNI_ERR;
+
+            display(0, "#### JVMTIagent: ... setting MethodExit events done\n");
+
+            methodsEventSet = JNI_TRUE;
+        }
+    }
+
+    if (stress_lev >= 1) {
+        /* ExceptionCatch events */
+        if (excCatchEventSet == JNI_FALSE) { /* don't set the event twice */
+            display(0, "#### JVMTIagent: setting ExceptionCatch events ...\n");
+
+            callbacks.ExceptionCatch = &ExceptionCatch;
+
+            if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+                    jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION_CATCH, NULL)))
+                return JNI_ERR;
+
+            excCatchEventSet = JNI_TRUE;
+
+            display(0, "#### JVMTIagent: ... setting ExceptionCatch events done\n");
+        }
+    }
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks,
+            jvmti, &callbacks, sizeof(callbacks))))
+        return JNI_ERR;
+    else
+        return 0;
+}
+
+static int enableEventsCaps() {
+    jvmtiCapabilities caps;
+
+    memset(&caps, 0, sizeof(jvmtiCapabilities));
+
+    /* add all capabilities */
+    caps.can_redefine_classes = 1;
+    caps.can_generate_breakpoint_events = 1;
+    caps.can_generate_all_class_hook_events = 1;
+    caps.can_generate_single_step_events = 1;
+    caps.can_generate_method_entry_events = 1;
+    caps.can_generate_method_exit_events = 1;
+    caps.can_generate_exception_events = 1;
+    caps.can_generate_compiled_method_load_events = 1;
+    caps.can_generate_field_access_events = 1;
+    caps.can_generate_field_modification_events = 1;
+    caps.can_generate_frame_pop_events = 1;
+    caps.can_generate_garbage_collection_events = 1;
+    caps.can_generate_monitor_events = 1;
+    caps.can_generate_native_method_bind_events = 1;
+    caps.can_generate_object_free_events = 1;
+    caps.can_generate_vm_object_alloc_events = 1;
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB2(AddCapabilities,
+            jvmti, &caps)))
+        return JNI_ERR;
+
+    /* Breakpoint events */
+    display(0, "#### JVMTIagent: setting Breakpoint events ...\n");
+
+    callbacks.Breakpoint = &Breakpoint;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting Breakpoint events done\n");
+
+    /* ClassFileLoadHook events */
+    display(0, "#### JVMTIagent: setting ClassFileLoadHook events ...\n");
+
+    callbacks.ClassFileLoadHook = &ClassFileLoadHook;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ClassFileLoadHook events done\n");
+
+    /* ClassLoad events */
+    display(0, "#### JVMTIagent: setting ClassLoad events ...\n");
+
+    callbacks.ClassLoad = &ClassLoad;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ClassLoad events done\n");
+
+    /* ClassPrepare events */
+    display(0, "#### JVMTIagent: setting ClassPrepare events ...\n");
+
+    callbacks.ClassPrepare = &ClassPrepare;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ClassPrepare events done\n");
+
+    /* CompiledMethodLoad events */
+    display(0, "#### JVMTIagent: setting CompiledMethodLoad events ...\n");
+
+    callbacks.CompiledMethodLoad = &CompiledMethodLoad;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting CompiledMethodLoad events done\n");
+
+    /* CompiledMethodUnload events */
+    display(0, "#### JVMTIagent: setting CompiledMethodUnload events ...\n");
+
+    callbacks.CompiledMethodUnload = &CompiledMethodUnload;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting CompiledMethodUnload events done\n");
+
+    /* DataDumpRequest events */
+    display(0, "#### JVMTIagent: setting DataDumpRequest events ...\n");
+
+    callbacks.DataDumpRequest = &DataDumpRequest;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_DATA_DUMP_REQUEST, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting DataDumpRequest events done\n");
+
+    /* DynamicCodeGenerated events */
+    display(0, "#### JVMTIagent: setting DynamicCodeGenerated events ...\n");
+
+    callbacks.DynamicCodeGenerated = &DynamicCodeGenerated;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_DYNAMIC_CODE_GENERATED, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting DynamicCodeGenerated events done\n");
+
+    /* Exception events */
+    display(0, "#### JVMTIagent: setting Exception events ...\n");
+
+    callbacks.Exception = &Exception;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting Exception events done\n");
+
+    /* FieldAccess events */
+    display(0, "#### JVMTIagent: setting FieldAccess events ...\n");
+
+    callbacks.FieldAccess = &FieldAccess;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_FIELD_ACCESS, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting FieldAccess events done\n");
+
+    /* FieldModification events */
+    display(0, "#### JVMTIagent: setting FieldModification events ...\n");
+
+    callbacks.FieldModification = &FieldModification;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_FIELD_MODIFICATION, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting FieldModification events done\n");
+
+    /* FramePop events */
+    display(0, "#### JVMTIagent: setting FramePop events ...\n");
+
+    callbacks.FramePop = &FramePop;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_FRAME_POP, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting FramePop events done\n");
+
+    /* GarbageCollectionFinish events */
+    display(0, "#### JVMTIagent: setting GarbageCollectionFinish events ...\n");
+
+    callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting GarbageCollectionFinish events done\n");
+
+    /* GarbageCollectionStart events */
+    display(0, "#### JVMTIagent: setting GarbageCollectionStart events ...\n");
+
+    callbacks.GarbageCollectionStart = &GarbageCollectionStart;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting GarbageCollectionStart events done\n");
+
+    /* MonitorContendedEnter events */
+    display(0, "#### JVMTIagent: setting MonitorContendedEnter events ...\n");
+
+    callbacks.MonitorContendedEnter = &MonitorContendedEnter;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting MonitorContendedEnter events done\n");
+
+    /* MonitorContendedEntered events */
+    display(0, "#### JVMTIagent: setting MonitorContendedEntered events ...\n");
+
+    callbacks.MonitorContendedEntered = &MonitorContendedEntered;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting MonitorContendedEntered events done\n");
+
+    /* MonitorWait events */
+    display(0, "#### JVMTIagent: setting MonitorWait events ...\n");
+
+    callbacks.MonitorWait = &MonitorWait;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAIT, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting MonitorWait events done\n");
+
+    /* MonitorWaited events */
+    display(0, "#### JVMTIagent: setting MonitorWaited events ...\n");
+
+    callbacks.MonitorWaited = &MonitorWaited;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_MONITOR_WAITED, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting MonitorWaited events done\n");
+
+    /* NativeMethodBind events */
+    display(0, "#### JVMTIagent: setting NativeMethodBind events ...\n");
+
+    callbacks.NativeMethodBind = &NativeMethodBind;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_NATIVE_METHOD_BIND, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting NativeMethodBind events done\n");
+
+    /* ObjectFree events */
+    display(0, "#### JVMTIagent: setting ObjectFree events ...\n");
+
+    callbacks.ObjectFree = &ObjectFree;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ObjectFree events done\n");
+
+    /* ThreadEnd events */
+    display(0, "#### JVMTIagent: setting ThreadEnd events ...\n");
+
+    callbacks.ThreadEnd = &ThreadEnd;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_END, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ThreadEnd events done\n");
+
+    /* ThreadStart events */
+    display(0, "#### JVMTIagent: setting ThreadStart events ...\n");
+
+    callbacks.ThreadStart = &ThreadStart;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting ThreadStart events done\n");
+
+    /* VMDeath events */
+    display(0, "#### JVMTIagent: setting VMDeath events ...\n");
+
+    callbacks.VMDeath = &VMDeath;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting VMDeath events done\n");
+
+    /* VMInit events */
+    display(0, "#### JVMTIagent: setting VMInit events ...\n");
+
+    callbacks.VMInit = &VMInit;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting VMInit events done\n");
+
+    /* VMStart events */
+    display(0, "#### JVMTIagent: setting VMStart events ...\n");
+
+    callbacks.VMStart = &VMStart;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_START, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting VMStart events done\n");
+
+    /* VMObjectAlloc events */
+    display(0, "#### JVMTIagent: setting VMObjectAlloc events ...\n");
+
+    callbacks.VMObjectAlloc = &VMObjectAlloc;
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB4(SetEventNotificationMode,
+            jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL)))
+        return JNI_ERR;
+    display(0, "#### JVMTIagent: ... setting VMObjectAlloc events done\n");
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(SetEventCallbacks,
+            jvmti, &callbacks, sizeof(callbacks))))
+        return JNI_ERR;
+
+    return 0;
+}
+
+static void clearJavaException(JNIEnv* jni_env) {
+    if (NSK_CPP_STUB1(ExceptionOccurred, jni_env)) {
+
+        NSK_CPP_STUB1(ExceptionDescribe, jni_env);
+        NSK_CPP_STUB1(ExceptionClear, jni_env);
+
+        NSK_CPP_STUB2(FatalError, jni_env,
+            "JVMTIagent: exception occurred in java code, aborting\n");
+    }
+}
+
+static int get_tok(char **src, char *buf, int buflen, char sep) {
+    int i;
+    char *p = *src;
+    for (i = 0; i < buflen; i++) {
+        if (p[i] == 0 || p[i] == sep) {
+            buf[i] = 0;
+            if (p[i] == sep) {
+                i++;
+            }
+            *src += i;
+            return i;
+        }
+        buf[i] = p[i];
+    }
+    /* overflow */
+    return 0;
+}
+
+static void doSetup(char *str) {
+    if (str == 0)
+        str = "";
+
+    if ((strcmp(str, "help")) == 0) {
+        printf("#### JVMTIagent usage: -agentlib:JVMTIagent[=[help]|[=[verbose]|[verbose2],[stress0|stress1|stress2|stress3]]]\n");
+        printf("####      where: help\tprint this message\n");
+        printf("####             verbose\tturn verbose mode on\n");
+        printf("####             verbose2\tturn extended verbose mode on (including reporting JVMTI events)\n");
+        printf("####             stress0, or empty value\tturn stress level 0 on (default mode):\n");
+        printf("####                   enable event generation except ExceptionCatch, MethodEntry/Exit, SingleStep\n");
+        printf("####             stress1\tturn stress level 1 on:\n");
+        printf("####                   enable generation of ExceptionCatch events\n");
+        printf("####             stress2\tturn stress level 2 on:\n");
+        printf("####                   enable generation of ExceptionCatch,\n");
+        printf("####                                        MethodEntry/Exit events\n");
+        printf("####             stress3\tturn stress level 3 on:\n");
+        printf("####                   enable generation of ExceptionCatch,\n");
+        printf("####                                        MethodEntry/Exit,\n");
+        printf("####                                        SingleStep events\n");
+        exit(1);
+    }
+
+    while (*str) {
+        char buf[1000];
+
+        if (!get_tok(&str, buf, sizeof(buf), ',')) {
+            printf("ERROR: JVMTIagent: bad option: \"%s\"!\n", str);
+            exit(1);
+        }
+        if ((strcmp(buf, "verbose")) == 0) {
+            printf("#### JVMTIagent: turned verbose mode on ####\n");
+            debug_mode = 1;
+        }
+        if ((strcmp(buf, "verbose2")) == 0) {
+            printf("#### JVMTIagent: turned extended verbose mode on ####\n");
+            debug_mode = 2;
+        }
+        if ((strcmp(buf, "stress0")) == 0) {
+            if (debug_mode > 0)
+                printf("#### JVMTIagent: turned stress level 0 on ####\n");
+            stress_lev = 0;
+        }
+        if ((strcmp(buf, "stress1")) == 0) {
+            if (debug_mode > 0)
+                printf("#### JVMTIagent: turned stress level 1 on ####\n");
+            stress_lev = 1;
+        }
+        if ((strcmp(buf, "stress2")) == 0) {
+            if (debug_mode > 0)
+                printf("#### JVMTIagent: turned stress level 2 on ####\n");
+            stress_lev = 2;
+        }
+        if ((strcmp(buf, "stress3")) == 0) {
+            if (debug_mode > 0)
+                printf("#### JVMTIagent: turned stress level 3 on ####\n");
+            stress_lev = 3;
+        }
+    }
+}
+
+static void getVerdict(JNIEnv *jni_env, const char *evnt) {
+    char error_msg[80];
+
+    if (vm_death_occured == TRUE) {
+        sprintf(error_msg, "JVMTIagent: getVerdict: %s event occured after VMDeath",
+            evnt);
+
+        if (jni_env==NULL) { /* some event callbacks have no pointer to jni */
+            printf("ERROR: %s\n", error_msg);
+            exit(97);
+        }
+        else
+            NSK_CPP_STUB2(FatalError, jni_env, error_msg);
+    }
+}
+
+static void display(int level, const char format[], ...) {
+    va_list ar;
+
+    if (debug_mode > level) {
+        va_start(ar, format);
+        vprintf(format, ar);
+        va_end(ar);
+    }
+}
+
+/* agent procedure */
+static void JNICALL
+agentProc(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) {
+}
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+    /* create JVMTI environment */
+    if (!NSK_VERIFY((jvmti =
+            nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
+        return JNI_ERR;
+
+    doSetup(options);
+
+    if (!NSK_JVMTI_VERIFY(NSK_CPP_STUB3(CreateRawMonitor,
+            jvmti, "_event_lock", &eventLock)))
+        return JNI_ERR;
+
+    if (enableEventsCaps() == 0 && addStressEvents() == 0) {
+        display(0, "#### JVMTIagent: all events were successfully enabled and capabilities/events callbacks set ####\n\n");
+    } else {
+        printf("ERROR(%s,%d): JVMTIagent terminated abnormally! ####\n",
+            __FILE__,__LINE__);
+        return JNI_ERR;
+    }
+
+    /* register agent proc and arg */
+    if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
+        return JNI_ERR;
+
+    return JNI_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/LocalProcess.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import nsk.share.*;
+
+import java.io.*;
+
+/**
+ * Wrapper for local process.
+ * <p>
+ * This class provides abilities to launch such process,
+ * redirect standard output streams, wait for process terminates
+ * or kill the process, and so on.
+ * <p>
+ * This object is finalized with <code>nsk.share.Finalizer</code>.
+ *
+ * @see nsk.share.FinalizableObject
+ * @see nsk.share.Finalizer
+ */
+
+public class LocalProcess extends FinalizableObject {
+
+    public final static int PROCESS_IS_ALIVE = 222;
+
+    private Process process;
+
+    protected Process getProcess() {
+        return process;
+    }
+
+    public void launch (String[] args) throws IOException {
+        System.out.println("Launching process by array of args: ");
+        for (int mm=0; mm < args.length; mm++) {
+            System.out.println("    args[" + Integer.toString(mm) + "]: >" +
+                               args[mm] + "<");
+
+        }
+
+        process = Runtime.getRuntime().exec(args);
+
+        Finalizer finalizer = new Finalizer(this);
+        finalizer.activate();
+    }
+
+    public void launch (String cmdLine) throws IOException {
+        System.out.println("Launching process by command line: " + cmdLine);
+
+        process = Runtime.getRuntime().exec(cmdLine);
+
+        Finalizer finalizer = new Finalizer(this);
+        finalizer.activate();
+    }
+
+    /** Return exit status. */
+    public int getStatus () {
+        return process.exitValue();
+    }
+
+    /** Check whether the process has been terminated. */
+    public boolean terminated() {
+        try {
+            int value = process.exitValue();
+            return true;
+        } catch (IllegalThreadStateException e) {
+            return false;
+        }
+    }
+
+    /** Wait until the process shutdown or crash. */
+    public int waitFor () throws InterruptedException {
+        return process.waitFor();
+    }
+
+    /**
+     * Wait until the process shutdown or crash for given timeout in milliseconds.
+     * Returns <code>LocalProcess.PROCESS_IS_ALIVE</code> if process is not terminated
+     * after timeout.
+     */
+
+    public int waitFor (long timeMillisec) throws InterruptedException {
+        final Object waitObject = new Object();
+
+        class Watcher extends Thread {
+            int exitCode = LocalProcess.PROCESS_IS_ALIVE;
+            Process process;
+
+            Watcher (Process process) {
+               this.process = process;
+            }
+
+            public void run () {
+                try {
+                    synchronized (this) {
+                       exitCode = process.waitFor();
+                    }
+                } catch (InterruptedException ie) {
+                }
+                synchronized (waitObject) {
+                    waitObject.notifyAll();
+                }
+            }
+
+            synchronized public int getExitCode() {
+                return exitCode;
+            }
+        }
+
+        Watcher watcher;
+        // yield control to watcher for timeMillisec time.
+        synchronized (waitObject) {
+            watcher = new Watcher(process);
+            watcher.start();
+
+            waitObject.wait(timeMillisec);
+        }
+
+        if (watcher.isAlive()) {
+            watcher.interrupt();
+        }
+
+        return watcher.getExitCode();
+    }
+
+    // --------------------------------------------------- //
+
+    /** Get a pipe to write to the process' stdin stream. */
+    public OutputStream getStdin () {
+        return process.getOutputStream();
+    }
+
+    /** Get a pipe to read the process' stdout stream. */
+    public InputStream getStdout () {
+        return process.getInputStream();
+    }
+
+    /** Get a pipe to read the process stderr stream. */
+    public InputStream getStderr () {
+        return process.getErrorStream();
+    }
+
+    /** Kill the process. */
+    protected void kill() {
+        process.destroy();
+    }
+
+    /**
+     * Finalize mirror by invoking <code>close()</code>.
+     *
+     * @throws Throwable if any throwable exception is thrown during finalization
+     */
+    protected void finalize() throws Throwable {
+        kill();
+        super.finalize();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Vector;
+
+import nsk.share.test.LazyFormatString;
+
+/**
+ * This class helps to print test-execution trace messages
+ * and filter them when execution mode is not verbose.
+ * <p>
+ * Verbose mode if defined by providing <i>-verbose</i> command line
+ * option, handled by <code>ArgumentParser</code>. Use <code>verbose()</code>
+ * method to determine which mode is used.
+ * <p>
+ * <code>Log</code> provides with two main methods to print messages:
+ * <ul>
+ *   <li> <code>complain(String)</code> - to print error message
+ *   <li> <code>display(String)</code> - to print additional log message
+ * </ul>
+ * No other way to print messages to the log stream should be used.
+ * <p>
+ * Error messages appeares in log stream in all modes. Additional log massages,
+ * printed with <code>display()</code> method will be filtered out, if log mode
+ * is not verbose. In verbose log made messages of both types are printed.
+ * Additionally, in verbose mode a summary of all occured errors will be printed
+ * at the program exit, by automatically invoking method
+ * <code>printErrorsSummary()</code>.
+ * <p>
+ * To provide printing messages from different sources into one log
+ * with distinct prefixes use internal <code>Log.Logger</code> class.
+ *
+ * @see #verbose()
+ * @see #complain(String)
+ * @see #display(String)
+ * @see ArgumentParser
+ * @see Log.Logger
+ */
+public class Log extends FinalizableObject {
+    /**
+     * Report step-by-step activity to this stream.
+     *
+     * @deprecated  Tests should not use this field directly.
+     */
+    protected PrintStream out = null;
+
+    /**
+     * Is log-mode verbose?
+     * Default value is <code>false</code>.
+     */
+    private boolean verbose = false;
+
+    /**
+     * Should log messages prefixed with timestamps?
+     * Default value is <code>false</code>.
+     */
+    private boolean timestamp = false;
+
+    /**
+     * Names for trace levels
+     */
+    public static final class TraceLevel {
+        public static final int TRACE_NONE = 0;
+        public static final int TRACE_IMPORTANT = 1;
+        public static final int TRACE_NORMAL = 2;
+        public static final int TRACE_VERBOSE = 3;
+        public static final int TRACE_DEBUG = 4;
+
+        public static final int DEFAULT = TRACE_IMPORTANT;
+
+        public static final Map<String, Integer> NAME_TO_LEVEL_MAP = new HashMap<String, Integer>();
+        static {
+            NAME_TO_LEVEL_MAP.put("none", TRACE_NONE);
+            NAME_TO_LEVEL_MAP.put("important", TRACE_IMPORTANT);
+            NAME_TO_LEVEL_MAP.put("info", TRACE_NORMAL);
+            NAME_TO_LEVEL_MAP.put("verbose", TRACE_VERBOSE);
+            NAME_TO_LEVEL_MAP.put("debug", TRACE_DEBUG);
+            NAME_TO_LEVEL_MAP.put("default", DEFAULT);
+        }
+
+        public static int nameToLevel(String value) throws IllegalArgumentException {
+            Integer level = NAME_TO_LEVEL_MAP.get(value.toLowerCase());
+            if ( level == null )
+                throw new IllegalArgumentException("Wrong trace level: " + value);
+
+            return level;
+        }
+
+        public static String getLevelsString() {
+            StringBuffer result = new StringBuffer();
+            for ( String s : NAME_TO_LEVEL_MAP.keySet() ) {
+                result.append(s).append(", ");
+            }
+            return result.substring(0, result.length() - 3);
+        }
+    }
+
+    /**
+     * Threshold value for printing trace messages for debugging purpose.
+     * Default value is <code>0</code> a.k.a. <code>TraceLevel.INFO</code>;
+     */
+    private int traceLevel = TraceLevel.DEFAULT;
+
+    /**
+     * Is printing errors summary enabled? Default value is <code>true</code>;
+     */
+    private boolean errorsSummaryEnabled = true;
+
+    /**
+     * Is printing saved verbose messages on error enabled? Default value is <code>true</code>;
+     */
+    private boolean verboseOnErrorEnabled = true;
+
+    /**
+     * This <code>errosBuffer</code> will keep all messages printed via
+     * <code>complain()</code> method for final summary output.
+     * Ensure that buffer has enough room for messages to keep,
+     * to minimize probability or OutOfMemory error while keeping
+     * an error message in stress tests.
+     */
+    private Vector<String> errorsBuffer = new Vector<String>(1000);
+
+    /**
+     * Most tests in nsk do not log exceptions, they only log an error message.
+     * This makes failure analysis harder.
+     * To solve this we will automatically generate Exceptions for error logs.
+     * To not log too many Exceptions, we try to log each unique error only once.
+     * <code>loggedExceptions</code> contains all messages that have already been logged.
+     */
+    private Set<String> loggedExceptions = new HashSet<String>();
+
+    /**
+     * This <code>logBuffer</code> will keep all messages printed via
+     * <code>display()</code> method in non-verbose mode until
+     * swithching verbose mode on or invoking <code>complain()</code>.
+     * Ensure that buffer has enough room for messages to keep,
+     * to minimize probability or OutOfMemory error while keeping
+     * an error message in stress tests.
+     */
+    private Vector<String> logBuffer = new Vector<String>(1000);
+
+    /**
+     * Did I already warned if output stream is not assigned?
+     */
+    private boolean noOutWarned = false;
+
+    /////////////////////////////////////////////////////////////////
+
+    /**
+     * Create new Log's only with <code>Log(out)</code> or with
+     * <code>Log(out,argsHandler)</code> constructors.
+     *
+     * @deprecated  Extending test class with Log is obsolete.
+     */
+    protected Log() {
+        // install finalizer to print errors summary at exit
+        Finalizer finalizer = new Finalizer(this);
+        finalizer.activate();
+
+        // Don't log exceptions from this method. It would just add unnecessary logs.
+        loggedExceptions.add("nsk.share.jdi.SerialExecutionDebugger.executeTests");
+    }
+
+    /**
+     * Incarnate new Log for the given <code>stream</code> and
+     * for non-verbose mode.
+     */
+    public Log(PrintStream stream) {
+        this();
+        out = stream;
+    }
+
+    /**
+     * Incarnate new Log for the given <code>stream</code>; and
+     * either for verbose or for non-verbose mode accordingly to
+     * the given <code>verbose</code> key.
+     */
+    public Log(PrintStream stream, boolean verbose) {
+        this(stream);
+        this.verbose = verbose;
+    }
+
+    /**
+     * Incarnate new Log for the given <code>stream</code>; and
+     * either for verbose or for non-verbose mode accordingly to
+     * the given <code>argsHandler</code>.
+     */
+    public Log(PrintStream stream, ArgumentParser argsParser) {
+        this(stream, argsParser.verbose());
+        traceLevel = argsParser.getTraceLevel();
+        timestamp = argsParser.isTimestamp();
+    }
+
+    /////////////////////////////////////////////////////////////////
+
+    /**
+     * Return <i>true</i> if log mode is verbose.
+     */
+    public boolean verbose() {
+        return verbose;
+    }
+
+    /**
+     * Return <i>true</i> if printing errors summary at exit is enabled.
+     */
+    public boolean isErrorsSummaryEnabled() {
+        return errorsSummaryEnabled;
+    }
+
+    /**
+     * Enable or disable printing errors summary at exit.
+     */
+    public void enableErrorsSummary(boolean enable) {
+        errorsSummaryEnabled = enable;
+    }
+
+    /**
+     * Return <i>true</i> if printing saved verbose messages on error is enabled.
+     */
+    public boolean isVerboseOnErrorEnabled() {
+        return errorsSummaryEnabled;
+    }
+
+    /**
+     * Enable or disable printing saved verbose messages on error.
+     */
+    public void enableVerboseOnError(boolean enable) {
+        verboseOnErrorEnabled = enable;
+    }
+
+    /**
+     * Enable or disable verbose mode for printing messages.
+     */
+    public void enableVerbose(boolean enable) {
+        if (!verbose) {
+            flushLogBuffer();
+        }
+        verbose = enable;
+    }
+
+    public int getTraceLevel() {
+        return traceLevel;
+    }
+
+    /**
+     * Set threshold for printing trace messages.
+     * Warning: trace level changes may NOT be observed by other threads immediately.
+     */
+    public void setTraceLevel(int level) {
+        traceLevel = level;
+    }
+
+    /**
+     * Return output stream of this <code>Log</code> object.
+     */
+    public PrintStream getOutStream() {
+        return out;
+    }
+
+    /**
+     * Returns a string that contains prefix concatenated
+     * with Throwable.printStackTrace() output.
+     */
+    public static String printExceptionToString(Object prefix, Throwable exception) {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        PrintWriter pw = new PrintWriter(bos);
+        pw.println(prefix);
+        exception.printStackTrace(pw);
+        pw.close();
+        return bos.toString();
+    }
+
+    /**
+     * Print <code>message</code> to the assigned output stream.
+     *
+     * @deprecated  Test ought to be quiet if log mode is non-verbose
+     *              and there is no errors found by the test. Methods
+     *              <code>display()</code> and <code>complain()</code>
+     *              are enough for testing purposes.
+     */
+    public synchronized void println(String message) {
+        doPrint(message);
+        if (!verbose() && isVerboseOnErrorEnabled()) {
+            keepLog(composeLine(message));
+        }
+    }
+
+    /**
+     * Print <code>message</code> to the assigned output stream,
+     * if log mode is <i>non</i>-verbose.
+     *
+     * @deprecated  Test ought to be quiet if log mode is non-verbose
+     *              and there is no errors found by the test. Methods
+     *              <code>display()</code> and <code>complain()</code>
+     *              are enough for testing purposes.
+     */
+    public synchronized void comment(String message) {
+        if (!verbose()) {
+            doPrint(message);
+        }
+    }
+
+    /**
+     * Print trace <code>message</code> to the assigned output stream,
+     * only if specified <code>level</code> is less or equal for the
+     * trace level specified in command line by <code>-trace.level</code>
+     * option.
+     */
+    public void trace(int level, Object message) {
+        if (level <= traceLevel) {
+            synchronized ( this ) {
+                doPrint("### TRACE " + level + ": " + message);
+            }
+        }
+    }
+    /**
+     * Print trace <code>message</code> and <code>exception</code> to
+     * the assigned output stream,
+     * only if specified <code>level</code> is less or equal for the
+     * trace level specified in command line by <code>-trace.level</code>
+     * option.
+     */
+    public void trace(int level, Object message, Throwable exception) {
+        if (level <= traceLevel) {
+            trace(level, printExceptionToString(message, exception));
+        }
+    }
+
+    /**
+     * Print <code>message</code> to the assigned output stream,
+     * if log mode is verbose. The <code>message</code> will be lost,
+     * if execution mode is non-verbose, and there is no error messages
+     * printed.
+     */
+    public synchronized void display(Object message) {
+        if (verbose()) {
+            doPrint(message.toString());
+        } else if (isVerboseOnErrorEnabled()) {
+            keepLog(composeLine(message.toString()));
+        } else {
+            // ignore
+        }
+    }
+
+    /**
+     * Print error <code>message</code> to the assigned output stream
+     * (or to stderr if output is not specified) and keep the message
+     * into <code>errorsBuffer</code>.
+     */
+    public synchronized void complain(Object message) {
+        if (!verbose() && isVerboseOnErrorEnabled()) {
+            PrintStream stream = findOutStream();
+            stream.println("#>  ");
+            stream.println("#>  WARNING: switching log to verbose mode,");
+            stream.println("#>      because error is complained");
+            stream.println("#>  ");
+            stream.flush();
+            enableVerbose(true);
+        }
+        String msgStr = message.toString();
+        printError(msgStr);
+        if (isErrorsSummaryEnabled()) {
+            keepError(msgStr);
+        }
+
+        logExceptionForFailureAnalysis(msgStr);
+    }
+
+    /**
+     * Print error <code>message</code> and <code>exception</code>
+     * to the assigned output stream
+     * (or to stderr if output is not specified) and keep the message
+     * into <code>errorsBuffer</code>.
+     */
+    public void complain(Object message, Throwable exception) {
+        if ( exception != null )
+            complain(printExceptionToString(message, exception));
+        else
+            complain(message);
+    }
+
+    /**
+     * Create an Exception and print the stack trace for an error msg.
+     * This makes it possible to detect a failure reason for this error.
+     */
+    private void logExceptionForFailureAnalysis(String msg) {
+        // Some error messages are formatted in multiple lines and with tabs.
+        // We clean the messages to help parse the stack traces for failure analysis.
+        // We keep at most 2 lines, otherwise the error message may be too long.
+        String[] lines = msg.split("[\r\n]+");
+        msg = lines.length >= 2 ? lines[0] + " " + lines[1] : lines[0];
+        msg = msg.replaceAll("\t", " ");
+
+        // Create a dummy exception just so we can print the stack trace.
+        TestFailure e = new TestFailure(msg);
+        StackTraceElement[] elements = e.getStackTrace();
+
+        final int callerIndex = 2; // 0=this function, 1=complain(), 2=caller
+        if (elements.length <= callerIndex) {
+            return;
+        }
+
+        // Only log the first complain message from each function.
+        // The reason is that some functions splits an error message
+        // into multiple lines and call complain() many times.
+        // We do not want a RULE for each of those calls.
+        // This means that we may miss some rules, but that
+        // is better than to create far too many rules.
+        String callerClass = elements[callerIndex].getClassName();
+        String callerMethod = elements[callerIndex].getMethodName();
+        String callerKey = callerClass + "." + callerMethod;
+        boolean isAlreadyLogged = loggedExceptions.contains(msg) || loggedExceptions.contains(callerKey);
+
+        if (!isAlreadyLogged) {
+            PrintStream stream = findOutStream();
+            stream.println("The following stacktrace is for failure analysis.");
+            e.printStackTrace(stream);
+        }
+
+        loggedExceptions.add(callerKey);
+        loggedExceptions.add(msg);
+    }
+
+    /////////////////////////////////////////////////////////////////
+
+    /**
+     * Redirect log to the given <code>stream</code>, and switch
+     * log mode to verbose.
+     * Prints errors summary to current stream, cancel current stream
+     * and switches to new stream. Turns on verbose mode for new stream.
+     *
+     * @deprecated  This method is obsolete.
+     */
+    protected synchronized void logTo(PrintStream stream) {
+        finalize(); // flush older log stream
+        out = stream;
+        verbose = true;
+    }
+
+    /////////////////////////////////////////////////////////////////
+
+    /**
+     * Print all messages from log buffer which were hidden because
+     * of non-verbose mode,
+     */
+    private synchronized void flushLogBuffer() {
+        if (!logBuffer.isEmpty()) {
+            PrintStream stream = findOutStream();
+            for (int i = 0; i < logBuffer.size(); i++) {
+                stream.println(logBuffer.elementAt(i));
+            }
+            stream.flush();
+        }
+    }
+
+    /**
+     * Return <code>out</code> stream if defined or <code>Sytem.err<code> otherwise;
+     * print a warning message when <code>System.err</code> is used first time.
+     */
+    private synchronized PrintStream findOutStream() {
+        PrintStream stream = out;
+        if (stream == null) {
+            stream = System.err;
+            if (!noOutWarned) {
+                noOutWarned = true;
+                stream.println("#>  ");
+                stream.println("#>  WARNING: switching log stream to stderr,");
+                stream.println("#>      because no output stream is assigned");
+                stream.println("#>  ");
+            };
+        };
+        stream.flush();
+        return stream;
+    }
+
+    /**
+     * Compose line to print possible prefixing it with timestamp.
+     */
+    private String composeLine(String message) {
+        if (timestamp) {
+            long time = System.currentTimeMillis();
+            long ms = time % 1000;
+            time /= 1000;
+            long secs = time % 60;
+            time /= 60;
+            long mins = time % 60;
+            time /= 60;
+            long hours = time % 24;
+            return "[" + hours + ":" + mins + ":" + secs + "." + ms + "] " + message;
+        }
+        return message;
+    }
+
+    /**
+     * Print the given <code>message</code> either to <code>out</code>
+     * stream, or to <code>System.err</code> if <code>out</code>
+     * stream is not specified.
+     */
+    private synchronized void doPrint(String message) {
+        PrintStream stream = findOutStream();
+        stream.println(composeLine(message));
+        stream.flush();
+    }
+
+    /**
+     * Print the given error <code>message</code> either to <code>out</code>
+     * stream, or to <code>System.err</code> if <code>out</code>
+     * stream is not specified.
+     */
+    private synchronized void printError(String message) {
+        // Print each line with the ERROR prefix:
+        BufferedReader br = new BufferedReader(new StringReader(message));
+        for (String line; ; ) {
+            try {
+                line = br.readLine();
+                if (line == null)
+                    break;
+                doPrint("# ERROR: " + line);
+            } catch (IOException e) {
+                throw new TestBug("Exception in Log.printError(): " + e);
+            };
+        }
+    }
+
+    /**
+     * Keep the given log <code>message</code> into <code>logBuffer</code>.
+     */
+    private synchronized void keepLog(String message) {
+        logBuffer.addElement(message);
+    }
+
+    /**
+     * Keep the given error <code>message</code> into <code>errorsBuffer</code>.
+     */
+    private synchronized void keepError(String message) {
+        errorsBuffer.addElement(message);
+    }
+
+    /**
+     * Print errors messages summary from errors buffer if any;
+     * print a warning message first.
+     */
+    private synchronized void printErrorsSummary() {
+        if (errorsBuffer.size() <= 0)
+            return;
+
+        PrintStream stream = findOutStream();
+        stream.println();
+        stream.println();
+        stream.println("#>  ");
+        stream.println("#>  SUMMARY: Following errors occured");
+        stream.println("#>      during test execution:");
+        stream.println("#>  ");
+        stream.flush();
+
+        for (Enumeration e = errorsBuffer.elements(); e.hasMoreElements(); ) {
+            printError((String) e.nextElement());
+        }
+    }
+
+    /**
+     * Print errors summary if mode is verbose, flush and cancel output stream.
+     */
+    protected void finalize() {
+        if (verbose() && isErrorsSummaryEnabled()) {
+            printErrorsSummary();
+        }
+        if (out != null)
+            out.flush();
+        out = null;
+    }
+
+    /**
+     * Perform finalization at the exit.
+     */
+    public void finalizeAtExit() {
+        finalize();
+    }
+
+    /**
+     * This class can be used as a base for each class that use <code>Log</code>
+     * for print messages and errors.
+     * <code>Logger</code> provides with ability to print such messages with
+     * specified prefix to make it possible to distinct messages printed from
+     * different sources.
+     *
+     * @see Log
+     */
+    public static class Logger {
+
+        /**
+         * Default prefix for messages.
+         */
+        public static final String LOG_PREFIX = "";
+
+        /**
+         * Log to print messages to.
+         */
+        protected Log log = null;
+
+        /**
+         * Prefix for messages.
+         */
+        protected String logPrefix = LOG_PREFIX;
+
+        /**
+         * Make <code>Logger</code> object with empty <code>Log</code> and
+         * default prefix.
+         * This method may be used only in derived class, that should specify
+         * the used <code>Log</code> object further and assign it to <code>log</code>.
+         *
+         * @see #log
+         * @see #setLogPrefix
+         */
+        protected Logger() {
+        }
+
+        /**
+         * Make <code>Logger</code> object for specified <code>Log</code>
+         * with default prefix.
+         *
+         * @see #setLogPrefix
+         */
+        public Logger(Log log) {
+            this.log = log;
+        }
+
+        /**
+         * Make <code>Logger</code> object for specified <code>Log</code> with
+         * given messages prefix.
+         */
+        public Logger(Log log, String prefix) {
+            this.log = log;
+            this.logPrefix = prefix;
+        }
+
+        /**
+         * Return <code>Log</code> object.
+         */
+        public Log getLog() {
+            return log;
+        }
+
+        /**
+         * Return output stream of this <code>Log</code> object.
+         */
+        public PrintStream getOutStream() {
+            return log.getOutStream();
+        }
+
+        /**
+         * Set prefix for printed messages.
+         */
+        public void setLogPrefix(String prefix) {
+            logPrefix = prefix;
+        }
+
+        /**
+         * Make printable message by adding <code>logPrefix<code> to it.
+         */
+        public String makeLogMessage(String message) {
+            return logPrefix + message;
+        }
+
+        /**
+         * Print trace message by invoking <code>Log.trace()</code>.
+         *
+         * @see Log#trace
+         */
+        public void trace(int level, String message) {
+            log.trace(level, makeLogMessage(message));
+        }
+
+        /**
+         * Print message by invoking <code>Log.println()</code>.
+         *
+         * @see Log#println
+         */
+        public void println(String message) {
+            log.println(makeLogMessage(message));
+        }
+
+        /**
+         * Print message by invoking <code>Log.display()</code>.
+         *
+         * @see Log#display
+         */
+        public void display(String message) {
+            log.display(makeLogMessage(message));
+        }
+
+        /**
+         * Complain about an error by invoking <code>Log.complain()</code> method.
+         *
+         * @see Log#complain
+         */
+        public void complain(String message) {
+            log.complain(makeLogMessage(message));
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class NativeUtils {
+    static {
+        System.loadLibrary("native_utils");
+    }
+
+    public static native long getCurrentPID();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ObjectInstancesManager.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+import java.util.*;
+
+/*
+ *  Class create/delete instances with given reference type and given referrers number
+ */
+public class ObjectInstancesManager
+{
+        public static String STRONG_REFERENCE = "STRONG";
+        public static String WEAK_REFERENCE = "WEAK";
+        public static String SOFT_REFERENCE = "SOFT";
+        public static String PHANTOM_REFERENCE = "PHANTOM";
+        public static String JNI_GLOBAL_REFERENCE = "JNI_GLOBAL";
+        public static String JNI_LOCAL_REFERENCE = "JNI_LOCAL";
+        public static String JNI_WEAK_REFERENCE = "JNI_WEAK";
+
+        // used to create references of all types
+        private static String USE_ALL_REFERENCE_TYPES = "ALL_REFERENCE_TYPES";
+
+        private Map<String, Collection<ReferringObjectSet>> instances = new TreeMap<String, Collection<ReferringObjectSet>>();
+
+        public static Set<String> primitiveArrayClassNames = new HashSet<String>();
+
+        static
+        {
+                primitiveArrayClassNames.add("boolean[]");
+                primitiveArrayClassNames.add("byte[]");
+                primitiveArrayClassNames.add("char[]");
+                primitiveArrayClassNames.add("int[]");
+                primitiveArrayClassNames.add("long[]");
+                primitiveArrayClassNames.add("float[]");
+                primitiveArrayClassNames.add("double[]");
+        }
+
+
+        public static Set<String> allReferenceTypes = new HashSet<String>();
+
+        static
+        {
+                allReferenceTypes.add(ObjectInstancesManager.STRONG_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.WEAK_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.SOFT_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.JNI_GLOBAL_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.JNI_LOCAL_REFERENCE);
+                allReferenceTypes.add(ObjectInstancesManager.JNI_WEAK_REFERENCE);
+        }
+
+        public static boolean isWeak(String type) {
+            return !(type.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE)
+                    || type.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE)
+                    || type.equals(ObjectInstancesManager.STRONG_REFERENCE));
+
+        }
+
+        public static Log log;
+
+        public ObjectInstancesManager(Log log)
+        {
+                ObjectInstancesManager.log = log;
+        }
+
+        // delete a given number of referrers
+        public void deleteReferrers(String className, int referrersCount, Set<String> referrerTypes)
+        {
+                Collection<ReferringObjectSet> objectInstances;
+
+                objectInstances = instances.get(className);
+
+                if(objectInstances == null)
+                {
+                        log.display("Error command 'deleteObjectInstances' is requsted: instances of class " + className + " was not created");
+                        System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                        return;
+                }
+
+                Iterator<ReferringObjectSet> iterator = objectInstances.iterator();
+
+                while(iterator.hasNext())
+                {
+                        ReferringObjectSet debugeeObjectReference = iterator.next();
+                        if (referrerTypes.isEmpty() || referrerTypes.contains(debugeeObjectReference.getReferenceType())) {
+                                debugeeObjectReference.delete(referrersCount);
+
+                                if(debugeeObjectReference.getReferrerCount() == 0)
+                                        iterator.remove();
+                        }
+                }
+        }
+
+        // delete all object referrers, it is equal to make object unreacheable
+        public void deleteAllReferrers(int count, String className)
+        {
+                Collection<ReferringObjectSet> objectInstances;
+
+                objectInstances = instances.get(className);
+
+                if(objectInstances == null)
+                {
+                        throw new TestBug("Command 'deleteObjectInstances' is requsted: instances of class " + className + " was not created");
+                }
+
+                Iterator<ReferringObjectSet> iterator = objectInstances.iterator();
+
+                if(count == 0)
+                        count = objectInstances.size();
+
+                for(int i = 0; i < count; i++)
+                {
+                        ReferringObjectSet debugeeObjectReference = iterator.next();
+                        debugeeObjectReference.deleteAll();
+
+                        iterator.remove();
+                }
+        }
+
+        // create object instance with referrers of all possible types
+        public void createAllTypeReferences(String className, int count)
+        {
+                createReferences(count, className, 1, allReferenceTypes);
+        }
+
+        // create a given number of object instances with given number of referrers
+        public void createReferences(int count, String className, int referrerCount, Set<String> referrerTypes)
+        {
+                Collection<ReferringObjectSet> objectInstances;
+
+                Class klass = null;
+
+                if(!primitiveArrayClassNames.contains(className))
+                {
+                        try
+                        {
+                                klass = Class.forName(className);
+                        }
+                        catch(ClassNotFoundException e)
+                        {
+                                log.display("Can't find class: " + className);
+                                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                                return;
+                        }
+                }
+
+                objectInstances = instances.get(className);
+
+                if(objectInstances == null)
+                {
+                        objectInstances = new ArrayList<ReferringObjectSet>();
+                        instances.put(className, objectInstances);
+                }
+
+                for(int i = 0; i < count; i++)
+                {
+                        try
+                        {
+                                Object instance;
+
+                                if(!primitiveArrayClassNames.contains(className))
+                                {
+                                        instance = klass.newInstance();
+                                }
+                                else
+                                {
+                                        instance = createPrimitiveTypeArray(className);
+                                }
+
+                                for(String type : referrerTypes) {
+                                        objectInstances.add(new ReferringObjectSet(instance, referrerCount, type));
+                                }
+                        }
+                        catch(Exception e)
+                        {
+                                log.display("Unexpected exception: " + e);
+                                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                        }
+                }
+        }
+
+        public Object createPrimitiveTypeArray(String typeName)
+        {
+                int arraySize = 1;
+
+                if(typeName.equals("boolean[]"))
+                        return new boolean[arraySize];
+                else
+                if(typeName.equals("byte[]"))
+                        return new byte[arraySize];
+                else
+                if(typeName.equals("char[]"))
+                        return new char[arraySize];
+                else
+                if(typeName.equals("int[]"))
+                        return new int[arraySize];
+                else
+                if(typeName.equals("long[]"))
+                        return new long[arraySize];
+                else
+                if(typeName.equals("float[]"))
+                        return new float[arraySize];
+                else
+                if(typeName.equals("double[]"))
+                        return new double[arraySize];
+                else
+                {
+                        throw new TestBug("Invalid primitive type array type name: " + typeName);
+                }
+        }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Oddity.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * Oddity exception is used to simulate C/C++ style <code>assert()</code>
+ * facility. It is thrown when an internal contradiction is revealed, which
+ * may do not indicate a bug in the JDI implementation or in the test.
+ */
+public class Oddity extends Failure {
+    /** Explain particular oddity. */
+    public Oddity (String message) {
+        super(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Pair.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class Pair<A, B> {
+    final public A first;
+    final public B second;
+
+    private Pair(A first, B second) {
+        this.first = first;
+        this.second = second;
+    }
+
+    public static <A, B> Pair<A, B> of(A first, B second) {
+        return new Pair<A, B>(first, second);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + first + ", " + second + ")";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Paragrep.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.*;
+import java.util.regex.*;
+
+/**
+ * Weak emulator of perl's grep function with very small functionality.
+ * This class does not use java.util.regexp classes which appear in
+ * JDK1.4 API.
+ *
+ * @see Grep
+ */
+
+public class Paragrep {
+
+    String[] stringArray;
+    /**
+     * Takes String array as character sequence for matching the pattern.
+     */
+    public Paragrep (String[] stringArray) {
+        this.stringArray = stringArray;
+    }
+
+    /**
+     * Returns number of non-interleaved occurences of the pattern string.
+     */
+    public int find (String pattern) {
+        if (pattern.length() == 0) {
+            throw new Failure("Empty string as input parameter for Grep.find(pattern) method");
+        }
+        int counter = 0;
+        for (int i = 0; i < stringArray.length; i++) {
+
+            String string = stringArray[i];
+            if (string != null) {
+                // Find all non-interleaved occurences of pattern in this string
+                for (int ind = 0; ind < string.length(); ) {
+                    int k = 0;
+                    if ((k = string.indexOf(pattern, ind)) >= 0) {
+                       counter++;
+                       ind = k + pattern.length();
+                    } else {
+                       break;
+                    }
+                }
+            }
+        }
+        return counter;
+    }
+
+    /**
+     * Returns all string in <code>stringArray</code> which have
+     * occurences of the pattern string.
+     */
+    public String[] findStrings (String pattern) {
+        if (pattern.length() == 0) {
+            throw new Failure("Empty string as input parameter for Grep.find(pattern) method");
+        }
+        Vector<String> v = new Vector<String>();
+        for (int i = 0; i < stringArray.length; i++) {
+            String string = stringArray[i];
+            if (string != null && string.indexOf(pattern) >= 0) {
+               v.add(string);
+            }
+        }
+        String[] result = new String[v.size()];
+        v.toArray(result);
+        return result;
+    }
+
+    /**
+     * Returns first string of stringArray which contains
+     * the pattern string or empty string othrewise.
+     */
+    public String findFirst (String pattern) {
+        if (pattern.length() == 0) {
+            throw new Failure("Empty string as input parameter for Paragrep.findFirst(pattern) method");
+        }
+        String result = "";
+        for (int i = 0; i < stringArray.length; i++) {
+            String string = stringArray[i];
+            if (string != null) {
+                if (string.indexOf(pattern) >= 0) {
+                    result = string;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns first string of stringArray which contains
+     * all of the pattern strings or empty string otherwise.
+     */
+    public String findFirst (Vector<String> patternVector) {
+        if (patternVector.isEmpty()) {
+            throw new Failure("Empty vector as input parameter for Paragrep.findFirst(patternVector) method");
+        }
+        String[] patterns = new String[patternVector.size()];
+        patternVector.toArray(patterns);
+        String result = "";
+        for (int i = 0; i < stringArray.length; i++) {
+            String string = stringArray[i];
+            if (string != null && string.length() > 0) {
+                for (int j = 0; j < patterns.length; j++) {
+                    String pattern = patterns[j];
+                    if (string.indexOf(pattern) >= 0) {
+                        if (j + 1 == patterns.length) {
+                            // found all patterns in the current string
+                            result = string;
+                            i = stringArray.length;
+                        }
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns count of strings in stringArray which contain
+     * all of the pattern strings.
+     */
+    public int find (Vector<String> patternVector) {
+        if (patternVector.isEmpty()) {
+            throw new Failure("Empty vector as input parameter for Paragrep.find(patternVector) method");
+        }
+        String[] patterns = new String[patternVector.size()];
+        patternVector.toArray(patterns);
+        int counter = 0;
+
+        for (int i = 0; i < stringArray.length; i++) {
+            String string = stringArray[i];
+            if (string != null && string.length() > 0) {
+                for (int j = 0; j < patterns.length; j++) {
+                    String pattern = patterns[j];
+                    if (string.indexOf(pattern) >= 0) {
+                        if (j + 1 == patterns.length) {
+                            // found all patterns in the current string
+                            counter++;
+                        }
+                    } else {
+                        break;
+                    }
+                }
+            }
+        }
+        return counter;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/PrintProperties.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.Properties;
+
+/**
+ * This program prints system properties.
+ */
+public class PrintProperties {
+        public static void main(String[] args) {
+                Properties pr = System.getProperties();
+                switch (args.length) {
+                case 0:
+                        pr.list(System.out);
+                        System.exit(0);
+                case 1:
+                        String value = pr.getProperty(args[0]);
+                        if (value == null) {
+                                System.err.println("Not found");
+                                System.exit(1);
+                        } else {
+                                System.out.println(value);
+                                System.exit(0);
+                        }
+                default:
+                        System.out.println("Usage:");
+                        System.out.println("    PrintProperties");
+                        System.out.println("    PrintProperties <property name>");
+                        System.exit(255);
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/RASagent.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.util.*;
+
+/**
+ * Class used as an agent for Java serviceability reliability testing (RAS).
+ * It sets different RAS options and/or modes for a special agent which
+ * actually performs the specified RAS testing.<br>
+ * The agent recognizes arguments, started with ''<code>-ras.</code>''. They
+ * may be as follows:<p>
+ * <li><code>-ras.help</code> - print usage message and exit
+ * <li><code>-ras.verbose</code> - verbose mode
+ * <li><code>-ras.invoke_run</code> - invoke the method <i>run(String[],PrintStream)</i>
+ * of the test instead of <i>main(String[])</i> which is invoked by default.
+ * <li><code>-ras.hotswap=&lt;stress_level&gt;</code> - enable JVMTI hotswap of
+ * the currently running test classes. Here are the possible HotSwap stress
+ * levels:<br>
+ * 0 - HotSwap off<br>
+ * 2 - HotSwap tested class in every JVMTI method entry event of running test
+ * (default mode)<br>
+ * 20 - HotSwap tested class in every JVMTI method entry event of every class<br>
+ * 3 - HotSwap tested class in every JVMTI single step event of running test<br>
+ * 4 - HotSwap tested class in every JVMTI exception event of running test<br>
+ * 40 - HotSwap tested class in every JVMTI exception event of every class<p>
+ */
+public class RASagent {
+    static final int HOTSWAP_OFF = 0;
+    static final int HOTSWAP_EVERY_METHOD_ENTRY = 2;
+    static final int HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS = 20;
+    static final int HOTSWAP_EVERY_SINGLE_STEP = 3;
+    static final int HOTSWAP_EVERY_EXCEPTION = 4;
+    static final int HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS = 40;
+
+    // path to the directory with class files of the invoked test
+    static String clfBasePath = null;
+
+    private static boolean verbose = false;
+
+    private static PrintStream out;
+
+    native static int setHotSwapMode(boolean vrb, int stress_lev,
+        String shortName);
+
+    public static void main(String argv[]) {
+        System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+    }
+
+    public static int run(String argv[], PrintStream out) {
+        return new RASagent().runThis(argv, out);
+    }
+
+    private int runThis(String argv[], PrintStream out) {
+        int skipArgs = 1; // number of arguments which must be skipped
+                          // for the invoked test
+        boolean invokeRun = false; // invoke the method "main" by default
+        int hotSwapMode = HOTSWAP_EVERY_METHOD_ENTRY; // HotSwap default stress level
+        int res;
+        String hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
+
+        RASagent.out = out;
+
+        if (argv.length != 0) {
+            // parse arguments for the RASagent and then skip them
+            while(argv[skipArgs-1].startsWith("-ras.")) {
+                if (argv[skipArgs-1].equals("-ras.verbose")) {
+                    verbose = true;
+                } else if (argv[skipArgs-1].equals("-ras.help")) {
+                    printHelp();
+                    return Consts.TEST_FAILED;
+                } else if (argv[skipArgs-1].equals("-ras.invoke_run")) {
+                    invokeRun = true;
+                } else if (argv[skipArgs-1].startsWith("-ras.hotswap=")) {
+                    try {
+                        hotSwapMode = Integer.parseInt(
+                           argv[skipArgs-1].substring(argv[skipArgs-1].lastIndexOf("=")+1));
+                    } catch (NumberFormatException e) {
+                        e.printStackTrace();
+                        out.println("\nERROR: RASagent: specified HotSwap mode \""
+                            + hotSwapMode + "\" is not an integer");
+                        printHelp();
+                        return Consts.TEST_FAILED;
+                    }
+                    switch(hotSwapMode) {
+                        case HOTSWAP_EVERY_METHOD_ENTRY:
+                            hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY";
+                            break;
+                        case HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS:
+                            hotSwapModeName = "HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS";
+                            break;
+                        case HOTSWAP_EVERY_SINGLE_STEP:
+                            hotSwapModeName = "HOTSWAP_EVERY_SINGLE_STEP";
+                            break;
+                        case HOTSWAP_EVERY_EXCEPTION:
+                            hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION";
+                            break;
+                        case HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS:
+                            hotSwapModeName = "HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS";
+                            break;
+                        default:
+                            out.println("\nERROR: RASagent: specified HotSwap mode \""
+                                + hotSwapMode + "\" is unrecognized");
+                            printHelp();
+                            return Consts.TEST_FAILED;
+                    }
+                }
+                skipArgs++;
+            }
+
+            String shortTestName = getTestNameAndPath(argv[skipArgs-1]);
+
+            display("\n#### RASagent: setting hotswap mode \""
+                + hotSwapModeName + "\" for class \""
+                + shortTestName + "\" ...");
+            if ((res = setHotSwapMode(verbose, hotSwapMode, shortTestName)) != 0) {
+                out.println("\nERROR: RASagent: unable to set HotSwap stress level for \""
+                    + shortTestName + "\", exiting");
+                return Consts.TEST_FAILED;
+            }
+            display("\n#### RASagent: ... setting hotswap mode done");
+
+            try {
+                Class testCls = Class.forName(argv[skipArgs-1]);
+                display("\n#### RASagent: main class \""
+                    + testCls.toString() + "\" loaded");
+
+                // copy arguments for the invoked test
+                String args[] = new String[argv.length-skipArgs];
+                System.arraycopy(argv, skipArgs, args, 0, args.length);
+
+                // invoke the test
+                if (invokeRun)
+                    return invokeRunMethod(testCls, args);
+                else
+                    return invokeMainMethod(testCls, args);
+            } catch(ClassNotFoundException e) {
+                // just pass: the invoked test is already a RAS specific one
+                out.println("\nWARNING: the test was not really run due to the following error:"
+                    + "\n\tunable to get the Class object for \""
+                    + argv[skipArgs-1] + "\"\n\tcaught: " + e);
+                return Consts.TEST_PASSED;
+            }
+
+        } else {
+            out.println("\nERROR: RASagent: required test name is absent in parameters list");
+            return Consts.TEST_FAILED;
+        }
+    }
+
+    /**
+     * Verify that test's class file exists with a path given as a parameter
+     * and, if so, store that path in the static field "clfBasePath".
+     */
+    private boolean pathValid(String pathToCheck, String testName) {
+        String fullPath = pathToCheck + File.separator
+            + testName.replace('.', File.separatorChar) + ".class";
+        File classFile = null;
+
+        display("\n#### RASagent: verifying class path\n<RASagent>\t"
+            + pathToCheck + " ...");
+        try {
+            classFile = new File(fullPath);
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            out.println("\nERROR: RASagent: verification of class file "
+                + fullPath + " failed: caught " + e);
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+
+        if (classFile.exists()) {
+            clfBasePath = pathToCheck;
+            display("<RASagent>\tthe class file exists:\n<RASagent>\t\t"
+                + fullPath + "\n<RASagent>\tclass file base directory found:\n"
+                + "<RASagent>\t\t" + clfBasePath
+                + "\n#### RASagent: ... class path verification done\n");
+            return true;
+        }
+        else {
+            display("<RASagent>\tno class file at location :\n\t\t"
+                + fullPath
+                + "\n#### RASagent: ... class path verification done\n");
+            return false;
+        }
+    }
+
+    /**
+     * Get short name of an invoked test (i.e. without package name) and
+     * store path to the directory with the test's class files.
+     */
+    private String getTestNameAndPath(String testName) {
+        String shortTestName = testName;
+        String packageName = "";
+
+        // if '.' occurs, it means that current test is inside a package
+        if (testName.lastIndexOf(".") != -1) {
+            shortTestName = testName.substring(testName.lastIndexOf(".")+1);
+            packageName = testName.substring(0, testName.lastIndexOf("."));
+        }
+
+        StringTokenizer clPathes = new StringTokenizer(
+            System.getProperty("java.class.path"), File.pathSeparator);
+
+        while(clPathes.hasMoreTokens()) {
+            String clPath = clPathes.nextToken();
+
+            // trying to load a class file defining the current test from
+            // this entry of "java.class.path": the class file may locate
+            // at the test's work directory or if it's already compiled,
+            // at any directory in classpath
+            if (pathValid(clPath, testName))
+                return shortTestName;
+        }
+
+        // directory with the test's class files was not found.
+        // Actually, it means that the invoked test has own Java
+        // options such as, for example, "-verify"
+        out.println("\nWARNING: the test was not really run due to the following reason:"
+            + "\n\tthe invoked test has the own Java option: "
+            + testName);
+        System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);
+
+        return null; // fake return for too smart javac
+    }
+
+    /**
+     * Invoke the method <i>main(String[])</i> of the test.
+     */
+    private int invokeMainMethod(Class testCls, String args[]) {
+        Class[] methType = { String[].class };
+        Object[] methArgs = { args };
+
+        return invokeMethod(testCls, "main", methType, methArgs);
+    }
+
+    /**
+     * Invoke the method <i>run(String[], PrintStream)</i> of the test.
+     */
+    private int invokeRunMethod(Class testCls, String args[]) {
+        Class[] methType = { String[].class, PrintStream.class };
+        Object[] methArgs = { args, out };
+
+        return invokeMethod(testCls, "run", methType, methArgs);
+    }
+
+    /**
+     * Low level invocation of the test.
+     */
+    private int invokeMethod(Class<?> testCls, String methodName,
+            Class methType[], Object methArgs[]) {
+
+        try {
+            Method testMeth = testCls.getMethod(methodName, methType);
+            display("\n#### RASagent: invoking method \""
+                + testMeth.toString() + "\" ...");
+
+            Object result = testMeth.invoke(null, methArgs);
+
+            display("\n#### RASagent: ... invocation of \""
+                + testMeth.toString() + "\" done");
+            if (result instanceof Integer) {
+                Integer retCode = (Integer) result;
+                return retCode.intValue();
+            }
+        } catch(NoSuchMethodException e) {
+            e.printStackTrace();
+            out.println("\nFAILURE: RASagent: unable to get method \""
+                + methodName + "\" in class "
+                + testCls + "\n\tcaught " + e);
+            return Consts.TEST_FAILED;
+        } catch(Exception e) {
+            e.printStackTrace();
+            out.println("\nFAILURE: RASagent: caught during invokation of the test class "
+                + testCls + " " + e);
+            return Consts.TEST_FAILED;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Load class bytes for HotSwap.
+     */
+    static byte[] loadFromClassFile(String signature) {
+        String testPath = clfBasePath + File.separator + signature.substring(
+                1, signature.length()-1).replace('/', File.separatorChar) + ".class";
+        File classFile = null;
+
+        display("\n#### RASagent: looking for class file\n<RASagent>\t"
+            + testPath + " ...");
+
+        try {
+            classFile = new File(testPath);
+        } catch (NullPointerException e) {
+            out.println("\nFAILURE: RASagent: path name to the redefining class file is null");
+        }
+
+        display("\n#### RASagent: loading " + classFile.length()
+            + " bytes from class file "+ testPath + " ...");
+        byte[] buf = new byte[(int) classFile.length()];
+        try {
+            InputStream in = new FileInputStream(classFile);
+            in.read(buf);
+            in.close();
+        } catch(FileNotFoundException e) {
+            e.printStackTrace();
+            out.println("\nFAILURE: RASagent: loadFromClassFile: file " +
+                classFile.getName() + " not found");
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        } catch (Exception e) {
+            e.printStackTrace();
+            out.println("\nFAILURE: RASagent: unable to load bytes from the file:\n");
+            out.println("\t" + testPath + ": caught " + e);
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+
+        display("\n#### RASagent: ... " + classFile.length() + " bytes loaded");
+
+        return buf;
+    }
+
+    /**
+     * This method is used in verbose mode. It prints paramter string only
+     * in case of verbose mode.
+     */
+    private static void display(String msg) {
+        if (verbose)
+            out.println(msg);
+    }
+
+    /**
+     * This method prints out RASagent usage message.
+     */
+    private static void printHelp() {
+        out.println("\nRASagent usage: RASagent [option, ...] test" +
+            "\n\t-ras.help                 print this message and exit" +
+            "\n\t-ras.verbose              verbose mode (off by default)" +
+            "\n\t-ras.hotswap=mode         enable HotSwap of the running test classes" +
+            "\n\t\twhere mode is:" +
+            "\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY
+                + " - hotswap tested class in its every method entry event" +
+            "\n\t\t\t" + HOTSWAP_EVERY_METHOD_ENTRY_FOR_EVERY_CLASS
+                + " - hotswap tested class in every method entry event for every class" +
+            "\n\t\t\t" + HOTSWAP_EVERY_SINGLE_STEP
+                + " - hotswap tested class in its every single step event" +
+            "\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION
+                + " - hotswap tested class in its every exception event" +
+            "\n\t\t\t" + HOTSWAP_EVERY_EXCEPTION_FOR_EVERY_CLASS
+                + " - hotswap tested class in every exception event for every class\n" +
+            "\n\t-ras.invoke_run           invoke the method run() of the test" +
+            "\n\t\tinstead of main() by default");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/README	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,128 @@
+Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and\\\/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+---------------------------------------------------------------------------------
+
+This directory contains source files of NSK tests framework
+shared between all NSK tests.
+
+Files located directly in this directory provide general support
+for all tests.
+
+Files in the subdirectories provide specific support for tests of
+particular subsuites.
+
+---------------------------------------------------------------------------------
+
+Short description of files:
+
+    common exceptions:
+        Failure,java, TestBug.java, Oddity.java
+    common constants:
+        Consts.java
+    parsing command line arguments:
+        ArgumentPareser.java
+    output of errors and messages:
+        Log.java
+    process running:
+        LocalProcess.java, IORedirector.java
+    class loading/unloading:
+        DummyClassLoader.java, ZipClassLoader.java,
+        CustomClassLoader.java, ClassUnloder.java
+    objects finalization:
+        Finalizable.java, FinalizableObject.java, Finalizer.java
+    threads synchronization:
+        Wicket.java
+    text processing:
+        Grep.java, Paragrep.java
+    timeouts handling:
+        Harakiri.java, TimeoutHandler.java
+    tree structures support:
+        Denotation.java, TreeNodesDenotation.java
+    RAS mode support:
+        RASagent.java, JVMTIagent.c
+    JVMDI tests support:
+        JVMDITools.h, JVMDITools.c
+
+Short description of subdirectories:
+
+    Alien       - support for accessing external tests (JCK)
+    native      - support for native part of NSK tests
+    jni         - support for JNI tests and accessing JNI API
+    jvmti       - support for JVMTI tests and accessing JVMTI API
+    jpda        - support for two-VMs JPDA tests
+    jdwp        - support for JDWP tests and accessing JDWP API
+    jdi         - support for JDI tests and accesing JDI API
+    jdb         - support for JDB tests and accessing JDB tool
+    monitoring  - support for monitoring tests and accessing Java Monitoring&Management API
+    sysdict     - support for System Dictionary tests
+    gc          - support for GC tests
+    regression  - support for regression tests for known bugs
+    split_verifier - support for Split Verifier tests
+
+For more detailed description see README files in subdirectories.
+
+---------------------------------------------------------------------------------
+
+Naming conventions
+
+Classes:
+
+    All shared classes are groupped into packages to prevent
+    name collision.
+
+    All classes exported directly from this directory are
+    of package:
+
+        nsk.share
+
+    All classes exported from subdirectories are of particular
+    subpackage, e.g.:
+
+        nsk.share.jpda
+        nsk.share.jdwp
+        nsk.share.jdi
+        nsk.share.jdb
+        nsk.share.monitoring
+        nsk.share.sysdict
+
+Native functions and macroses:
+
+    Most native functions have special prefix to prevent linking collisions.
+    Most macroses also have special prefix and are wrote in upper register.
+
+    Here is typical naming scheme used for native functions and macroses:
+
+        share/native
+            functions: nsk_*
+            macroses:  NSK_*
+
+        share/jni
+            functions: nsk_jni_*
+            macroses:  NSK_JNI_*
+
+        share/jvmti
+            functions: nsk_jvmti_*
+            macroses:  NSK_JVMTI_*
+
+    However, some native functions and macroses do not follow this scheme,
+    in order to preserve compatibility with old tests.
+
+---------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+
+/*
+ * This class create/delete reference with given type.
+ *
+ * Supported reference types are:
+ * - strong
+ * - soft
+ * - weak
+ * - phantom
+ * - jni local
+ * - jni global
+ * - jni weak
+ */
+public class ReferringObject
+{
+        static
+        {
+                System.loadLibrary("JNIreferences");
+        }
+
+        public final static int maxJNIGlobalReferences = 1000;
+        public final static int maxJNIWeakReferences = 1000;
+
+        private Object reference;
+
+        private String referenceType;
+
+        //used for storing jni global and jni weak references
+        private int referenceIndex;
+
+        public ReferringObject(Object object, String referenceType)
+        {
+                this.referenceType = referenceType;
+
+                if(referenceType.equals(ObjectInstancesManager.STRONG_REFERENCE))
+                {
+                        createStrongReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
+                {
+                        createSoftReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
+                {
+                        createWeakReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
+                {
+                        createPhantomReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
+                {
+                        createJNIGlobalReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
+                {
+                        createJNILocalReference(object);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
+                {
+                        createJNIWeakReference(object);
+                }
+                else
+                        throw new IllegalArgumentException("Invalid reference type: " + referenceType);
+        }
+
+        public void delete()
+        {
+                if(referenceType == null)
+                {
+                        throw new TestBug("Reference type is null");
+                }
+
+                if(referenceType.equals(ObjectInstancesManager.SOFT_REFERENCE))
+                {
+                        if(reference == null)
+                        {
+                                throw new TestBug("Reference is null for SoftReference");
+                        }
+
+                        if(((SoftReference)reference).get() == null)
+                        {
+                     //           throw new TestBug("Test execution error: SoftReference was collected");
+                        }
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.WEAK_REFERENCE))
+                {
+                        if(reference == null)
+                        {
+                                throw new TestBug("Reference is null for WeakReference");
+                        }
+
+                        if(((WeakReference)reference).get() == null)
+                        {
+                       //         throw new TestBug("Test execution error: WeakReference was collected");
+                        }
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.PHANTOM_REFERENCE))
+                {
+                        if(reference == null)
+                        {
+                                throw new TestBug("Reference is null for PhantomReference");
+                        }
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_GLOBAL_REFERENCE))
+                {
+                        deleteJNIGlobalReferenceNative(referenceIndex);
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_LOCAL_REFERENCE))
+                {
+                        deleteJNILocalReference();
+                }
+                else
+                if(referenceType.equals(ObjectInstancesManager.JNI_WEAK_REFERENCE))
+                {
+                    try {
+                        deleteJNIWeakReferenceNative(referenceIndex);
+                    } catch (Throwable t)
+                    {
+
+                    }
+                }
+
+                reference = null;
+        }
+
+        private void createStrongReference(Object object)
+        {
+                reference = object;
+        }
+
+        private void createSoftReference(Object object)
+        {
+                reference = new SoftReference<Object>(object);
+        }
+
+        private void createWeakReference(Object object)
+        {
+                reference = new WeakReference<Object>(object);
+        }
+
+        private void createPhantomReference(Object object)
+        {
+                reference = new PhantomReference<Object>(object, new ReferenceQueue<Object>());
+        }
+
+        private void createJNIGlobalReference(Object object)
+        {
+                referenceIndex = createJNIGlobalReferenceNative(object, maxJNIGlobalReferences);
+
+                if(referenceIndex < 0)
+                {
+                        throw new TestBug("Error on creation of JNI_Global reference, Possible number of JNI_Global references exceeded max available value!");
+                }
+        }
+
+        /*
+         * Since jni local reference valid only for duration of native method call, to create jni local reference
+         * special thread is created which enter in native method, create jni local reference and wait
+         */
+        private void createJNILocalReference(Object object)
+        {
+                this.reference = object;
+
+                jniLocalReferenceThread = new JNILocalReferenceThread();
+                jniLocalReferenceThread.start();
+
+                // wait till JNI local reference will be created
+                jniLocalReferenceThread.createWhicket.waitFor();
+
+                reference = null;
+        }
+
+        private void deleteJNILocalReference()
+        {
+                // notify JNI method that JNI local reference is not needed any more and could be released
+                jniLocalReferenceThread.deleteWhicket.unlock();
+
+                try
+                {
+                        jniLocalReferenceThread.join(1000 * 60 * 2);
+
+                        if(jniLocalReferenceThread.isAlive())
+                        {
+                                throw new TestBug("JNI_Local_Reference thread can't finish execution");
+                        }
+                }
+                catch(InterruptedException e)
+                {
+                        throw new TestBug("deleteJNILocalReference was interrupted");
+                }
+        }
+
+        private void createJNIWeakReference(Object object)
+        {
+                referenceIndex = createJNIWeakReferenceNative(object, maxJNIWeakReferences);
+
+                if(referenceIndex < 0)
+                {
+                        throw new TestBug("Error on creation of JNI_Weak reference. Possible number of JNI_Weak references exceeded max available value!");
+                }
+        }
+
+        class JNILocalReferenceThread
+                extends Thread
+        {
+                Wicket createWhicket = new Wicket();
+                Wicket deleteWhicket = new Wicket();
+
+                public void run()
+                {
+                        createJNILocalReferenceNative(reference, createWhicket, deleteWhicket);
+                }
+        }
+
+        private JNILocalReferenceThread jniLocalReferenceThread;
+
+        private native int createJNIGlobalReferenceNative(Object object, int maxJNIGlobalReferences);
+
+        private native void deleteJNIGlobalReferenceNative(int index);
+
+        private native void createJNILocalReferenceNative(Object object, Wicket createWhicket, Wicket deleteWhicket);
+
+        private native int createJNIWeakReferenceNative(Object object, int maxJNIWeakReferences);
+
+        private native void deleteJNIWeakReferenceNative(int index);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ReferringObjectSet.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/*
+ *  Class create a number of referrers to given object
+ */
+public class ReferringObjectSet
+{
+        private Collection<ReferringObject> referringObjects;
+        private String referenceType;
+
+        public ReferringObjectSet(Object object, int referringCount, String referenceType)
+        {
+                this.referenceType = referenceType;
+                referringObjects = new ArrayList<ReferringObject>(referringCount);
+
+                for(int i = 0; i < referringCount; i++)
+                        referringObjects.add(new ReferringObject(object, referenceType));
+        }
+
+        public void delete(int count)
+        {
+                if((count < 0) || (count > referringObjects.size()))
+                {
+                        throw new TestBug("Invalid 'count' value: " + count + ", size=" + referringObjects.size());
+                }
+
+                Iterator<ReferringObject> iterator = referringObjects.iterator();
+
+                for(int i = 0; i < count; i++)
+                {
+                        ReferringObject referringObject = iterator.next();
+                        referringObject.delete();
+
+                        iterator.remove();
+                }
+        }
+
+        public void deleteAll()
+        {
+                delete(referringObjects.size());
+        }
+
+        public String getReferenceType() {
+            return referenceType;
+        }
+
+        public int getReferrerCount()
+        {
+                return referringObjects.size();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/StringGoldChecker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class StringGoldChecker extends AbstractGoldChecker {
+
+    private final String goldenString;
+
+    public StringGoldChecker(String goldenString) {
+        this.goldenString = goldenString;
+    }
+
+    @Override
+    protected String getGoldenString() {
+        return goldenString;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TestBug.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+/**
+ * Thrown when it becomes obvious that the test algorithm
+ * works incorrectly (for example - tries to write to debugee's
+ * stdin after it is already redirected, or something of the
+ * kind).
+ */
+public class TestBug extends Failure {
+        /** Explain particular failure. */
+        public TestBug(String message) {
+                super(message);
+        }
+
+        /** Enwrap another throwable. */
+        public TestBug(Throwable throwable) {
+                super(throwable);
+        }
+
+        public TestBug(String message, Throwable throwable) {
+                super(message, throwable);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TestFailure.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class TestFailure extends RuntimeException {
+    public TestFailure() {
+        super();
+    }
+
+    public TestFailure(String message) {
+        super(message);
+    }
+
+    public TestFailure(String message, Throwable e) {
+        super(message, e);
+    }
+
+    public TestFailure(Throwable e) {
+        super(e);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TestJNIError.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share;
+
+public class TestJNIError
+        extends Error
+{
+        public TestJNIError(String message)
+        {
+                super(message);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TimeoutHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.*;
+
+/**
+ * This class can be used to set timeout for test execution.
+ */
+public class TimeoutHandler {
+
+    /**
+     * Test execution timeout in minutes.
+     */
+    private int waitTime;
+
+    /**
+     * Make new <code>TimeoutHandler</code> object for timeout value
+     * specified in command line arguments.
+     */
+    public TimeoutHandler(ArgumentParser argumentHandler) {
+        this.waitTime = argumentHandler.getWaitTime();
+    }
+
+    /**
+     * Perform test execution in separate thread and wait for
+     * thread finishes or timeout exceeds.
+     */
+    public void runTest(Thread testThread) {
+        long millisec = waitTime * 60 * 1000;
+        testThread.start();
+        try {
+            testThread.join(millisec);
+        } catch (InterruptedException ex) {
+            throw new Failure(ex);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.util.*;
+
+/**
+ * This denotation provides naming and indexing for nodes
+ * of a binary, or ternary, or <tt>n</tt>-ary tree.
+ *
+ * <p>Here, <tt>n</tt> would be the length of a symbols
+ * string used as an alphabeth for nodes naming. For a
+ * binary tree, <tt>n=2</tt>, and an aplhabeth could be
+ * the <tt>"LR"</tt> string. This implies the following
+ * naming for tree nodes:
+ * <pre>
+ *              (empty)
+ *             /       \
+ *            L         R
+ *          /   \     /   \
+ *         LL   LR   RL   RR
+ *        /  \ /  \ /  \ /  \
+ * </pre>
+ *
+ * <p>Anyway, the tree root node is named with the empty
+ * string <tt>""</tt> and is indexed with 2-zeroes array
+ * <tt>{0,0}</tt>.
+ *
+ * <p>Index for a tree node is 2-elements <tt>int[]</tt>
+ * array. The 1st element is the node's level in a tree.
+ * The 2nd element is the item's number among all nodes of
+ * that level; provided that node items are enumerated from
+ * <tt>0</tt> to <tt>n</tt><sup>level</sup><tt>-1</tt>.
+ * Given a level, lexicographic order is assumed for the
+ * nodes of the same level.
+ *
+ * <p>For example: given the above sample tree, the node
+ * <tt>"L"</tt> has the index <tt>{1,0}</tt>, while the
+ * node <tt>"RL"</tt> has the index <tt>{2,2}</tt>.
+ *
+ * <p>In general case, ordering of characters used for nodes
+ * naming is implied by the given alphabeth. This may differ
+ * from the ``natural'' ordering. For example, if alphabeth
+ * is <tt>"ZYX...CBA"</tt>, then ordering for nodes would be
+ * opposite to ``natural''.
+ */
+public class TreeNodesDenotation extends Denotation {
+    /**
+     * Symbols to denote tree nodes.
+     *
+     * @see #TreeNodeDenotation(String)
+     */
+    private String alphabeth;
+
+    /**
+     * Standard denotation for a binary tree; alphabeth
+     * is <tt>"LR"</tt>.
+     *
+     * @see #TreeNodesDenotation(String)
+     */
+    public TreeNodesDenotation() {
+        this("LR");
+    }
+
+    /**
+     * Denotation for nodes of a tree.
+     *
+     * <p>Each tree node is marked with a string of symbols
+     * from the given <tt>alphabeth</tt>. A string length
+     * equals to the node's level. The root node is always
+     * denoted with the empty string.
+     *
+     * <p>For example, an <tt>alphabeth</tt> for a binary
+     * tree could be <tt>"LR"</tt>, or <tt>"01"</tt>, or
+     * any 2-symbols string. However, <tt>"lL"</tt> or
+     * <tt>"rR"</tt> would be illegal because of collision
+     * between upper- and lower- case letters.
+     *
+     * <p>In general case, it is illegal for <tt>alphabeth</tt>
+     * to contain two or several copies of the same symbol.
+     * This constructor deems lower- and upper-case variants
+     * of the same letter are the same symbol.
+     *
+     * @throws IllegalArgumentException If the <tt>alphabeth</tt>
+     * looks illegal.
+     */
+    public TreeNodesDenotation(String alphabeth) {
+        if (alphabeth.length() == 0)
+            throw new IllegalArgumentException("empty alphabeth");
+        // Check for lower- to upper- case collision:
+        this.alphabeth = alphabeth.toUpperCase();
+        int length = this.alphabeth.length();
+        Set<Character> pool = new HashSet<Character>(); // still empty
+        for (int i=0; i<length; i++)
+            pool.add(new Character(this.alphabeth.charAt(i)));
+        if (pool.size() != length)
+            throw new IllegalArgumentException("collision: " + alphabeth);
+    }
+
+    /**
+     * Check if the <tt>name</tt> is legal, and return the
+     * numeric index for the tree node denoted by the given
+     * <tt>name</tt>.
+     *
+     * @throws IllegalArgumentException If the <tt>name</tt>
+     * is illegal.
+     */
+    public int[] indexFor(String name) {
+        int level = name.length();
+        int factor = alphabeth.length();
+        long item = 0;
+        for (int i=0; i<level; i++) {
+            char symbol = Character.toUpperCase(name.charAt(i));
+            int position = alphabeth.indexOf(symbol);
+            if (position < 0)
+                throw new IllegalArgumentException("unknown symbol: " + name);
+            item = item*factor + position;
+            if (item < 0 || item > Integer.MAX_VALUE)
+                throw new IllegalArgumentException("too long name: " + name);
+        };
+        int[] index = new int [] { level, (int)item };
+        return index;
+    }
+
+    /**
+     * Check if the <tt>index[]</tt> is legal, and return
+     * a symbolic name for the tree node denoted by the
+     * given <tt>index[]</tt>.
+     *
+     * @throws IllegalArgumentException If the <tt>index[]</tt>
+     * is illegal.
+     */
+    public String nameFor(int[] index) {
+        if (index.length != 2)
+            throw new IllegalArgumentException(
+                "index dimention: " + index.length);
+        StringBuffer name = new StringBuffer(); // still empty
+        int level = index[0];
+        int item  = index[1];
+        if (level < 0 || item < 0)
+            throw new IllegalArgumentException(
+                "negative index: " + level + ", " + item);
+        int factor = alphabeth.length();
+        for (int i=0; i<level; i++) {
+            int k = item % factor;
+            name.append(alphabeth.charAt(k));
+            item = item / factor;
+        };
+        if (item != 0)
+            throw new IllegalArgumentException(
+                "out of range: {"+ index[0] + "," + index[1] + "}");
+        return new String(name.reverse());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Wicket.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share;
+
+import java.io.PrintStream;
+
+/**
+ * Wicket provides a means for one or more threads to suspend execution
+ * (to wait) until notified by one or more other threads that some set
+ * of locks is now open.
+ *
+ * <p>Wicket instances are intended to be used generally in the following
+ * scenarios:
+ *
+ *   <ul><li>One thread starts one or more child threads and waits until the
+ *   child threads to be started.
+ *
+ *   <li>One thread starts one or more child threads and waits until at least
+ *   one of the child threads to be started.
+ *
+ *   <li>One or more child threads wait until a main thread lets them
+ *   to finish.
+ *
+ *   <li>Disable the current thread for thread scheduling purposes, for up to
+ *   the specified waiting time.</ul>
+ */
+
+public class Wicket {
+
+    /** Number of closed locks, can be greater or equal to zero */
+    private int count;
+
+    /** Number of waiters **/
+    private int waiters = 0;
+
+    /** Enable debug output */
+    private PrintStream debugOutput = null;
+
+    /** Wicket's string identifier */
+    private String name = "";
+
+    /**
+     * Construct a Wicket with only one closed lock.
+     */
+    public Wicket() {
+        this(1);
+    }
+
+    /**
+     * Construct a Wicket with the given number of closed locks.
+     *
+     * @param _name Wicket's identifier
+     * @param _count the initial number of closed locks
+     * @param _debugOutput whether to print debug info or not
+     * @throws IllegalArgumentException if count is less than 1
+     */
+    public Wicket(String _name, int _count, PrintStream _debugOutput) {
+        this(_count);
+        name = _name;
+        debugOutput = _debugOutput;
+    }
+
+    /**
+     * Construct a Wicket with the given number of closed locks.
+     *
+     * @param count the initial number of closed locks
+     * @throws IllegalArgumentException if count is less than 1
+     */
+    public Wicket(int count) {
+        if (count < 1)
+            throw new IllegalArgumentException(
+                "count is less than one: " + count);
+        this.count = count;
+    }
+
+    /**
+     * Wait for all locks of this Wicket to be open.
+     *
+     * <p>If all locks are already open then returns immediately.
+     *
+     * <p>If at least one lock is still closed then the current thread becomes
+     * disabled for thread scheduling purposes and lies dormant until all
+     * the locks will be open by some other threads. One lock can be open
+     * by invoking the unlock method for this Wicket.
+     *
+     * <p>Please note, that the method would ignore Thread.interrupt() requests.
+     */
+    public synchronized void waitFor() {
+        ++waiters;
+        if (debugOutput != null) {
+            debugOutput.printf("Wicket %s: waitFor()\n", name);
+        }
+
+        while (count > 0) {
+            try {
+                wait();
+            } catch (InterruptedException e) {}
+        }
+        --waiters;
+    }
+
+    /**
+     * Wait for all locks of this Wicket to be open within the given
+     * period of time.
+     *
+     * <p>If all locks are already open then returns immediately with zero.
+     *
+     * <p>If the time is equal to zero, the method will not
+     * wait and returns a number of closed locks,
+     * if all locks are open, the return value is zero.
+     *
+     * <p>If at least one lock is still closed then the current thread becomes
+     * disabled for thread scheduling purposes and lies dormant until
+     * of the two things happens:
+     *
+     *   <ul><li>Some other threads invoke the unlock method for this Wicket
+     *   to open all the closed locks; or
+     *
+     *   <li>The specified waiting time elapses.</ul>
+     *
+     * <p>If all locks are open then the return value is 0.
+     *
+     * <p>If the specified waiting time elapses and some locks are still closed
+     * then the return value is equal to number of closed locks.
+     *
+     * <p>Please note, that the method would ignore Thread.interrupt() requests.
+     *
+     * @param timeout the maximum time to wait in milliseconds
+     * @return the number of closed locks
+     * @throws IllegalArgumentException if timeout is less than 0
+     */
+    public synchronized int waitFor(long timeout) {
+        if (debugOutput != null) {
+            debugOutput.printf("Wicket %s: waitFor(%d)\n", name, timeout);
+        }
+
+        if (timeout < 0)
+            throw new IllegalArgumentException(
+                "timeout value is negative: " + timeout);
+        ++waiters;
+        long waitTime = timeout;
+        long startTime = System.currentTimeMillis();
+        while (count > 0 && waitTime > 0) {
+            try {
+                wait(waitTime);
+            } catch (InterruptedException e) {}
+            waitTime = timeout - (System.currentTimeMillis() - startTime);
+        }
+        --waiters;
+        return (count);
+    }
+
+    /**
+     * Unlock one closed lock.
+     *
+     * <p>Open a lock, reducing the number of closed locks by one.
+     *
+     * <p>If last closed lock is opened then all of the threads waiting
+     * by invoking the waitFor method for this Wicket will be released
+     * and re-enabled for thread scheduling purposes.
+     *
+     * @throws IllegalStateException if there is no one closed lock
+     */
+    public synchronized void unlock() {
+        if (debugOutput != null) {
+            debugOutput.printf("Wicket %s: unlock()\n", name);
+        }
+
+        if (count == 0)
+            throw new IllegalStateException("locks are already open");
+
+        --count;
+        if (count == 0) {
+            notifyAll();
+        }
+    }
+
+    /**
+     * Unlock all closed locks.
+     *
+     * <p>Open all closed locks, setting the number of closed locks to zero.
+     *
+     * <p>If any threads are waiting by invoking the waitFor method for
+     * this Wicket then they will be released and re-enabled for thread
+     * scheduling purposes.
+     */
+    public synchronized void unlockAll() {
+        if (debugOutput != null) {
+            debugOutput.printf("Wicket %s: unlockAll()\n", name);
+        }
+
+        count = 0;
+        notifyAll();
+    }
+
+    /**
+     * Return current number of waiters - threads that are currently
+     * waiting using one of waitFor methods.
+     *
+     * @return number of waiters
+     */
+    public synchronized int getWaiters() {
+        if (debugOutput != null) {
+            debugOutput.printf("Wicket %s: getWaiters()\n", name);
+        }
+        return waiters;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODRunnerArgParser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import nsk.share.*;
+import java.util.*;
+
+public class AODRunnerArgParser extends ArgumentParser {
+
+    public static final String jarAgentParam = "ja";
+
+    public static final String nativeAgentParam = "na";
+
+    public static final String targetAppParam = "target";
+
+    public static final String javaOptsParam = "javaOpts";
+
+    public static final String testedJdkParam = "jdk";
+
+    private static List<String> supportedOptions;
+
+    static {
+        supportedOptions = new ArrayList<String>();
+        supportedOptions.add(jarAgentParam);
+        supportedOptions.add(nativeAgentParam);
+        supportedOptions.add(targetAppParam);
+        supportedOptions.add(javaOptsParam);
+        supportedOptions.add(testedJdkParam);
+    }
+
+    private List<AgentInformation> agents;
+
+    public AODRunnerArgParser(String[] args) {
+        super(args);
+    }
+
+    protected boolean checkOption(String option, String value) {
+        if (super.checkOption(option, value))
+            return true;
+
+        if (!supportedOptions.contains(option))
+            return false;
+
+        if (option.equals(jarAgentParam)) {
+            addAgentInfo(true, value);
+        }
+
+        if (option.equals(nativeAgentParam)) {
+            addAgentInfo(false, value);
+        }
+
+        return true;
+    }
+
+    protected void checkOptions() {
+        if (agents == null) {
+            agents = new ArrayList<AgentInformation>();
+        }
+    }
+
+    private void addAgentInfo(boolean jarAgent, String unsplittedAgentsString) {
+        if (agents == null) {
+            agents = new ArrayList<AgentInformation>();
+        }
+
+        String agentStrings[];
+
+        if (unsplittedAgentsString.contains(","))
+            agentStrings = unsplittedAgentsString.split(",");
+        else
+            agentStrings = new String[]{unsplittedAgentsString};
+
+        for (String agentString : agentStrings) {
+            int index = agentString.indexOf('=');
+
+            if (index > 0) {
+                String pathToAgent = agentString.substring(0, index);
+                String options = agentString.substring(index + 1);
+                agents.add(new AgentInformation(jarAgent, pathToAgent, options));
+            } else {
+                agents.add(new AgentInformation(jarAgent, agentString, null));
+            }
+        }
+    }
+
+    public String getTargetApp() {
+        if (!options.containsKey(targetAppParam))
+            throw new TestBug("Target application isn't specified");
+
+        return options.getProperty(targetAppParam);
+    }
+
+    public String getTestedJDK() {
+        if (!options.containsKey(testedJdkParam))
+            throw new TestBug("Tested JDK isn't specified");
+
+        return options.getProperty(testedJdkParam);
+    }
+
+    public String getJavaOpts() {
+        return options.getProperty(javaOptsParam, "");
+    }
+
+    public List<AgentInformation> getAgents() {
+        return agents;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTargetArgParser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import nsk.share.*;
+import java.util.*;
+
+public class AODTargetArgParser extends ArgumentParser {
+
+    public static final String agentsNumberParam = "agentsNumber";
+
+    public static final String socketPortParam = "port";
+
+    private int expectedAgentsNumber;
+
+    private int port;
+
+    private static List<String> supportedOptions;
+
+    static {
+        supportedOptions = new ArrayList<String>();
+        supportedOptions.add(agentsNumberParam);
+        supportedOptions.add(socketPortParam);
+    }
+
+    public AODTargetArgParser(String[] args) {
+        super(args);
+    }
+
+    protected boolean checkOption(String option, String value) {
+        if (super.checkOption(option, value))
+            return true;
+
+        if (!supportedOptions.contains(option))
+            return false;
+
+        if (option.equals(agentsNumberParam)) {
+            expectedAgentsNumber = Integer.parseInt(value);
+            if (expectedAgentsNumber < 0)
+                throw new TestBug("Invalid value of '" + option + "'");
+        } else if (option.equals(socketPortParam)) {
+            port = Integer.parseInt(value);
+            if (port <= 0 || port > 65535)
+                throw new TestBug("Invalid value of '" + option + "':" + port +" (it is expected to be in the range [1..65535]");
+        }
+
+        return true;
+    }
+
+    public int getExpectedAgentsNumber() {
+        if (!options.containsKey(agentsNumberParam))
+            throw new TestBug("Number of expected agents isn't specified");
+
+        return expectedAgentsNumber;
+    }
+
+    public int getPort() {
+        if (!options.containsKey(socketPortParam))
+            return -1;
+
+        return port;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import java.io.*;
+import nsk.share.*;
+import nsk.share.jpda.SocketIOPipe;
+
+/*
+ Class AODTestRunner is part of the framework used in the AttachOnDemand tests
+ (tests against Attach API, API from package com.sun.tools.attach).
+
+ AODTestRunner is used as main class in AttachOnDemand tests, it performs following
+ actions:
+ - starts target application
+
+ - finds VM id for target VM (this id is needed for dynamic attach)
+
+ - by default AODTestRunner tries to attach specified via command line agents to target VM
+ (subclasses can override this default behavior)
+
+ - waits for target application completion
+
+Target application class, agents that should be attached, JDK used to run target application and
+VM options passed to target VM should be specified via command line.
+ */
+public class AODTestRunner {
+
+    public static final String targetAppIdProperty = "vmsqe.aod.targetAppId";
+    public static final String appIdProperty = "vmsqe.aod.AppId";
+
+    public static final long TARGET_APP_CONNECT_TIMEOUT = 5 * 60 * 1000; // 5 min
+
+    public static final long TARGET_APP_WORK_TIMEOUT = 30 * 60 * 1000; // 30 min (standard VM testbase test timeout)
+
+    protected Log log;
+
+    protected SocketIOPipe pipe;
+
+    protected ProcessExecutor targetAppExecutor;
+
+    // target application ready for attach
+    public static final String SIGNAL_READY_FOR_ATTACH = "ready";
+
+    // target application may finish execution
+    public static final String SIGNAL_FINISH = "finish";
+
+    protected AODRunnerArgParser argParser;
+
+    protected AODTestRunner(String[] args) {
+        log = new Log(System.out, true);
+
+        argParser = createArgParser(args);
+    }
+
+    /*
+     * This method is introduced to let subclasses to create its own parsers
+     */
+    protected AODRunnerArgParser createArgParser(String[] args) {
+        return new AODRunnerArgParser(args);
+    }
+
+    protected void doTestActions(String targetVMId) throws Throwable {
+        AgentsAttacher attacher = new AgentsAttacher(targetVMId, argParser.getAgents(), log);
+        attacher.attachAgents();
+    }
+
+    protected String getCurrentVMId() {
+        String currentVMId = "" + ProcessHandle.current().pid();
+        log.display("Current VM id was identified: " + currentVMId);
+
+        return currentVMId;
+    }
+
+    protected void runTest() {
+
+        try {
+            String targetAppId = System.getProperty(targetAppIdProperty);
+            if(targetAppId == null || targetAppId.isEmpty()) {
+                // use PID as default appID
+                targetAppId = "" + ProcessHandle.current().pid();
+            }
+            /*
+             * Create target application id required by the Utils.findVMIdUsingJPS
+             */
+            String targetAppCmd =
+                    // path to java
+                    argParser.getTestedJDK() + File.separator + "bin" + File.separator + "java " +
+                            // VM property to identify VM running target application
+                            "-D" + appIdProperty + "=" + targetAppId +  " " +
+                            // VM opts
+                            argParser.getJavaOpts() + " -XX:+EnableDynamicAgentLoading " +
+                            // target application class
+                            argParser.getTargetApp() + " " +
+                            // additional target application parameter - number of
+                            // agents that will be attached
+                            "-" + AODTargetArgParser.agentsNumberParam + " " + argParser.getAgents().size();
+
+            pipe = SocketIOPipe.createServerIOPipe(log, 0, TARGET_APP_CONNECT_TIMEOUT);
+            targetAppCmd += " -" + AODTargetArgParser.socketPortParam + " " + pipe.getPort();
+
+            log.display("Starting target application: " + targetAppCmd);
+            targetAppExecutor = new ProcessExecutor(targetAppCmd, TARGET_APP_WORK_TIMEOUT, "TargetApp");
+            targetAppExecutor.startProcess();
+
+            /*
+             * Don't try to attach agents until target application isn't initialized
+             */
+            String signal = pipe.readln();
+            log.display("Signal received: '" + signal + "'");
+            if ((signal == null) || !signal.equals(SIGNAL_READY_FOR_ATTACH))
+                throw new TestBug("Unexpected TargetApplication signal: '" + signal + "'");
+
+            String targetVMId = Long.toString(targetAppExecutor.pid());
+            log.display("Target VM id was identified: " + targetVMId);
+
+            doTestActions(targetVMId);
+
+            /*
+             * When test actions finished let target application finish execution
+             */
+            log.display("Sending signal: '" + SIGNAL_FINISH + "'");
+            pipe.println(SIGNAL_FINISH);
+
+            targetAppExecutor.waitForProcess();
+
+            File file = new File(targetAppId);
+            if (file.exists()) {
+                file.deleteOnExit();
+            }
+
+            if (targetAppExecutor.getExitCode() != 0) {
+                throw new Failure("Target application finished with non-zero code " + targetAppExecutor.getExitCode());
+            }
+
+            postTargetExitHook();
+
+        } catch (Failure f) {
+            throw f;
+        } catch (Throwable t) {
+            throw new Failure("Unexpected exception during test execution: " + t, t);
+        } finally {
+            if (pipe != null) {
+                pipe.close();
+            }
+            if (targetAppExecutor != null) {
+                targetAppExecutor.destroyProcess();
+            }
+        }
+    }
+
+    /*
+     * Allow users of this class to specify actions to be taken after the target exits
+     */
+    protected void postTargetExitHook() {
+        // do nothing by default
+    }
+
+    public static String createApplicationId() {
+        return new Long(System.currentTimeMillis()).toString();
+    }
+
+    public static void main(String[] args) {
+        new AODTestRunner(args).runTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AbstractJarAgent.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import java.lang.instrument.*;
+import java.io.*;
+import nsk.share.*;
+
+/*
+
+AbstractJarAgent is base class for java agents used in AttachOnDemand tests
+(tests against Attach API, API from package com.sun.tools.attach).
+
+In all AttachOnDemand tests the same algorithm is used:
+    - java application where agent is loaded to (target application) based on
+     class nsk.share.aod.TargetApplicationWaitingAgents starts and waits when
+     test agents will be loaded
+
+    - special application (nsk.share.jvmti.aod.AgentsAttacher) loads test agents
+    in the target application using Attach API
+
+    - when agent is loaded it notifies target application about that and executes
+    test-specific actions. When agent execution is completed it also notifies
+    target application about that
+
+    - when all test agents finish execution target application checks its status
+    (passed or failed) and also finishes
+
+Each java agent should have method 'agentmain' where only agent initialization should be done,
+main agent's actions should be executed in special thread started from 'agentmain'.
+Class AbstractJarAgent incapsulates actions common for all java agents: agent initialization,
+starting thread executing agent's actions and communication with target application.
+
+In most cases test agents should override only method 'agentActions' and its 'agentmain'
+should contain only call of the method 'AbstractJarAgent.runJarAgent'.
+
+Typical agent class looks like this:
+
+public class agentExample extends AbstractJarAgent {
+
+    protected void init(String[] args) {
+        // parse agent's options and do test-specific initialization
+    }
+
+    protected void agentActions() {
+        // do test specific actions
+    }
+
+    public static void agentmain(final String options, Instrumentation inst) {
+        new agentExample().runJarAgent(options, inst);
+    }
+}
+ */
+abstract public class AbstractJarAgent {
+
+    private boolean finishedSuccessfully = true;
+
+    private Log log;
+
+    protected void display(String message) {
+        log.display(outputPrefix + message);
+    }
+
+    protected void complain(String message) {
+        log.complain(outputPrefix + message);
+    }
+
+    protected void logThrowable(Throwable t) {
+        t.printStackTrace(log.getOutStream());
+    }
+
+    /*
+     * Instrumentation object passed to the 'agentmain' method
+     */
+    protected Instrumentation inst;
+
+    private String name;
+
+    private String outputPrefix;
+
+    private String pathToNewByteCode;
+
+    protected String pathToNewByteCode() {
+        return pathToNewByteCode;
+    }
+
+    /*
+     * Subclasses should report about test failures using this method
+     */
+    protected void setStatusFailed(String errorMessage) {
+        finishedSuccessfully = false;
+        complain("ERROR: " + errorMessage);
+    }
+
+    /*
+     * Initialization method, called from agentmain before method agentActions is called
+     * (it introduced for overriding in subclasses)
+     */
+    protected void init(String[] args) {
+    }
+
+    protected static class AgentOption {
+        public String name;
+        public String value;
+        public AgentOption(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+    }
+
+    protected AgentOption parseAgentArgument(String arg) {
+        int index = arg.indexOf('=');
+        if (index <= 0) {
+            throw new TestBug("Invalid agent parameters format");
+        }
+        return new AgentOption(arg.substring(0, index), arg.substring(index + 1));
+    }
+
+    static protected final String agentNameOption = "-agentName";
+
+    static protected final String pathToNewByteCodeOption = "-pathToNewByteCode";
+
+    /*
+     * Parse agent's options, initialize common parameters
+     */
+    private void defaultInit(String[] args) {
+        for (int i = 0; i < args.length; i++) {
+            AgentOption option = parseAgentArgument(args[i]);
+            if (option.name.equals(agentNameOption)) {
+                name = option.value;
+                outputPrefix = name + ": ";
+            } else if (option.name.equals(pathToNewByteCodeOption)) {
+                pathToNewByteCode = option.value;
+            }
+        }
+
+        if (name == null)
+            throw new TestBug("Agent name wasn't specified");
+
+        log = new Log(System.out, true);
+    }
+
+    /*
+     * Special thread which is started from agentmain method and executing main
+     * agent's actions. When agent completes execution AgentThread notifies
+     * target application about that.
+     */
+    class AgentThread extends Thread {
+
+        AgentThread() {
+            super("Jar agent thread (agent: " + name + ")");
+        }
+
+        public void run() {
+            try {
+                agentActions();
+            } catch (Throwable t) {
+                setStatusFailed("Unexpected exception in the JarAgent: " + t);
+                logThrowable(t);
+            } finally {
+                TargetApplicationWaitingAgents.agentFinished(name, finishedSuccessfully);
+            }
+        }
+    }
+
+    /*
+     * This methods parses agent's options, initializes agent, notifies target application
+     * that agent is started and starts thread executing main agent's actions.
+     * Agents used in AttachOnDemand tests should call this method from its agentmain methods.
+     */
+    public final void runJarAgent(String options, Instrumentation inst) {
+        if (options == null)
+            throw new TestBug("Agent options weren't specified");
+
+        this.inst = inst;
+
+        String[] args = options.split(" ");
+
+        // initialize common parameters
+        defaultInit(args);
+
+        // test-specific initialization
+        init(args);
+
+        // notify target application that agent was loaded and initialized
+        TargetApplicationWaitingAgents.agentLoaded(name);
+
+        // start special thread executing test-specific actions
+        new AgentThread().start();
+    }
+
+    /*
+     * Actions specific for test should be realized in this method.
+     * This method is called from special thread started from agentmain method
+     * after agent initialization
+     */
+    abstract protected void agentActions() throws Throwable;
+
+
+    /*
+     * Create ClassDefinition object for given class, path to the new class file
+     * is specified in the parameter 'pathToByteCode'
+     */
+    protected static ClassDefinition createClassDefinition(Class<?> klass,
+            String pathToByteCode) throws IOException {
+        File classFile = new File(pathToByteCode + File.separator +
+                klass.getName().replace(".", File.separator) +
+                ".class");
+
+        if (classFile.length() > Integer.MAX_VALUE)
+            throw new Failure("Class file '" + classFile.getName() + " 'too large");
+
+        byte data[] = new byte[(int)classFile.length()];
+
+        DataInputStream in = null;
+        try {
+            in = new DataInputStream(new FileInputStream(classFile));
+            in.readFully(data);
+        } finally {
+            if (in != null)
+                in.close();
+        }
+
+        return new ClassDefinition(klass, data);
+    }
+
+    /*
+     * Redefine given class using path to byte code specified with options -pathToNewByteCode
+     */
+    protected void redefineClass(Class<?> klass) throws Throwable {
+        if (pathToNewByteCode() == null)
+            throw new TestBug("Path to new class files wasn't specified");
+
+        ClassDefinition newClassDef = createClassDefinition(klass, pathToNewByteCode());
+        inst.redefineClasses(newClassDef);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentInformation.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+/*
+ * Class contains information about dynamically attached agent
+ */
+public class AgentInformation {
+
+    // counters used for unique agent names generation
+
+    private static int jarAgentsCounter;
+
+    private static int nativeAgentsCounter;
+
+    public boolean jarAgent;
+
+    public String pathToAgent;
+
+    public String agentOptions;
+
+    public AgentInformation(boolean jarAgent, String pathToAgent, String options, boolean addAgentNameOption) {
+        this.jarAgent = jarAgent;
+        this.pathToAgent = pathToAgent;
+        this.agentOptions = options;
+
+        // add to agent options additional parameter - agent name (it used by nsk.share.aod framework)
+
+        String name;
+
+        if (jarAgent)
+            name = "JarAgent-" + jarAgentsCounter++;
+        else
+            name = "NativeAgent-" + nativeAgentsCounter++;
+
+        if (addAgentNameOption) {
+            if (this.agentOptions == null) {
+                this.agentOptions = "-agentName=" + name;
+            } else {
+                this.agentOptions += " -agentName=" + name;
+            }
+        }
+    }
+
+    public AgentInformation(boolean jarAgent, String pathToAgent, String options) {
+        this(jarAgent, pathToAgent, options, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AgentsAttacher.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import nsk.share.*;
+import java.io.IOException;
+import java.util.*;
+import com.sun.tools.attach.*;
+
+/*
+ * This class loads java and native agents in the running VM using Attach API
+ * (API from package com.sun.tools.attach).
+ */
+public class AgentsAttacher {
+
+    protected String targetVMId;
+
+    protected List<AgentInformation> agents;
+
+    protected Log log;
+
+    public AgentsAttacher(String targetVMId, List<AgentInformation> agents, Log log) {
+        this.targetVMId = targetVMId;
+        this.agents = agents;
+        this.log = log;
+    }
+
+    public void attachAgents() {
+        VirtualMachine vm = null;
+
+        try {
+            log.display("Trying to get VirtualMachine object");
+            vm = VirtualMachine.attach(targetVMId);
+        } catch (AttachNotSupportedException e) {
+            log.complain("Unexpected AttachNotSupportedException during VirtualMachine.attach: " + e);
+            e.printStackTrace(log.getOutStream());
+        } catch (IOException e) {
+            log.complain("Unexpected IOException during VirtualMachine.attach: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+        if (vm == null) {
+            failed("Unable to create VirtualMachine object");
+        }
+
+        log.display("VirtualMachine was created: " + vm);
+
+        try {
+            for (AgentInformation agentInfo : agents) {
+                tryToLoadAgent(vm, agentInfo.pathToAgent, agentInfo.agentOptions, agentInfo.jarAgent);
+            }
+        } finally {
+            try {
+                log.display("Detaching from the VM '" + vm + "'");
+                vm.detach();
+            } catch (IOException e) {
+                failed("Unexpected IOException during detaching: " + e, e);
+            }
+        }
+    }
+
+    protected void tryToLoadAgent(VirtualMachine vm, String agent, String agentOptions, boolean jarAgent) {
+        boolean agentLoaded = false;
+
+        Throwable failureCause = null;
+
+        try {
+            if (jarAgent) {
+                log.display("Trying to load jar agent: '" + agent + "' (agent options: '" + agentOptions + "')");
+                vm.loadAgent(agent, agentOptions);
+            } else {
+                log.display("Trying to load native agent: '" + agent + "' (agent options: '" + agentOptions + "')");
+                vm.loadAgentLibrary(agent, agentOptions);
+            }
+            log.display("Agent was loaded");
+            agentLoaded = true;
+        } catch (AgentLoadException e) {
+            failureCause = e;
+            log.complain("Unexpected AgentLoadException during agent loading: " + e);
+            if (jarAgent) {
+                log.complain("(probably the agent does not exist, or cannot be started in the manner specified in "
+                        + "the java.lang.instrument specification)");
+            } else {
+                log.complain("(probably agent library does not exist, or cannot be loaded for another reason)");
+            }
+            e.printStackTrace(log.getOutStream());
+        } catch (AgentInitializationException e) {
+            failureCause = e;
+            log.complain("Unexpected AgentInitializationException during agent loading: " + e);
+            if (jarAgent) {
+                log.complain("(agentmain have thrown an exception)");
+            } else {
+                log.complain("Agent_OnAttach function returned an error: " + e.returnValue());
+            }
+            e.printStackTrace(log.getOutStream());
+        } catch (IOException e) {
+            failureCause = e;
+            log.complain("Unexpected IOException during agent loading: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+        if (!agentLoaded) {
+            if (failureCause != null)
+                failed("Couldn't attach agent to the target application", failureCause);
+            else
+                failed("Couldn't attach agent to the target application");
+        }
+    }
+
+    private void failed(String errorMessage) {
+        throw new Failure(errorMessage);
+    }
+
+    private void failed(String errorMessage, Throwable t) {
+        throw new Failure(errorMessage, t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/DummyTargetApplication.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import nsk.share.*;
+import nsk.share.jpda.SocketIOPipe;
+
+/*
+Class TargetApplication is part of the framework used in the AttachOnDemand tests
+(tests against Attach API, API from package com.sun.tools.attach).
+
+This class is used in tests where main test application uses Attach API, but doesn't load agents to the another VM.
+In these test there are 2 java applications: main application using Attach API and another
+'dummy' application which should be alive while main application is working.
+
+To synchronize main and dummy application SocketIOPipe is used: when DummyTargetApplication starts
+it sends signal that it is ready for test and waits for signal permitting finish execution
+(socket number used for connection establishing should be passed via command line).
+ */
+public class DummyTargetApplication {
+
+    protected Log log = new Log(System.out, true);
+
+    protected AODTargetArgParser argParser;
+
+    protected SocketIOPipe pipe;
+
+    public DummyTargetApplication(String[] args) {
+        argParser = new AODTargetArgParser(args);
+    }
+
+    protected void targetApplicationActions() {
+        // do nothing by default
+    }
+
+    public void runTargetApplication() {
+        pipe = SocketIOPipe.createClientIOPipe(log, "localhost", argParser.getPort(), 0);
+        log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");
+        pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);
+
+        targetApplicationActions();
+
+        String signal = pipe.readln();
+        log.display("Signal received: '" + signal + "'");
+
+        if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))
+            throw new TestBug("Unexpected signal: '" + signal + "'");
+    }
+
+    public static void main(String[] args) {
+        new DummyTargetApplication(args).runTargetApplication();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/ProcessExecutor.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.*;
+
+public class ProcessExecutor {
+
+    private String[] cmdLine;
+
+    private long timeout;
+
+    private boolean printProcessOutput;
+
+    private String processOutputPrefix;
+
+    private InputStreamReaderThread outReader;
+
+    private InputStreamReaderThread errReader;
+
+    private Process startedProcess;
+
+    private ProcessWaiterThread processWaiter;
+
+    private long expectedFinishTime;
+
+    private volatile boolean executionCompleted;
+
+    private int exitCode;
+
+    private class InputStreamReaderThread extends Thread {
+        private BufferedReader in;
+
+        private String outputPrefix;
+
+        private List<String> output = new ArrayList<String>();
+
+        private volatile boolean streamWasAbruptlyClosed;
+
+        private Throwable unexpectedException;
+
+        public InputStreamReaderThread(InputStream in, String prefix) {
+            this.in = new BufferedReader(new InputStreamReader(in));
+            this.outputPrefix = prefix;
+            setDaemon(true);
+        }
+
+        public void streamWasAbruptlyClosed(boolean newValue) {
+            streamWasAbruptlyClosed = newValue;
+        }
+
+        public void run() {
+            try {
+                while (true) {
+                    String line = in.readLine();
+                    if (line == null)
+                        return;
+
+                    output.add(line);
+
+                    if (printProcessOutput)
+                        System.out.println(outputPrefix + line);
+                }
+            } catch (IOException e) {
+                if (!streamWasAbruptlyClosed) {
+                    unexpectedException = e;
+                    e.printStackTrace( );
+                }
+            } catch (Throwable t) {
+                unexpectedException = t;
+                t.printStackTrace( );
+            }
+        }
+
+        void checkStatus() {
+            if (unexpectedException != null)
+                throw new Failure("Exception was thrown during InputStreamReaderThread work: " + unexpectedException,
+                        unexpectedException);
+        }
+    }
+
+    private class ProcessWaiterThread extends Thread {
+
+        private Throwable unexpectedException;
+
+        private Process process;
+
+        private InputStreamReaderThread outReader;
+
+        private InputStreamReaderThread errReader;
+
+        ProcessWaiterThread(Process process, InputStreamReaderThread outReader, InputStreamReaderThread errReader) {
+            this.process = process;
+            this.outReader = outReader;
+            this.errReader = errReader;
+
+            setDaemon(true);
+        }
+
+        public void run() {
+            try {
+                exitCode = process.waitFor();
+                outReader.join();
+                errReader.join();
+
+                synchronized (ProcessWaiterThread.this) {
+                    executionCompleted = true;
+                    ProcessWaiterThread.this.notify();
+                }
+            } catch (InterruptedException e) {
+                /*
+                 * ProcessWaiterThread is interrupted if started process
+                 * didn't finish in expected time
+                 */
+            } catch (Throwable t) {
+                unexpectedException = t;
+                t.printStackTrace();
+            }
+        }
+
+        void checkStatus() {
+            if (unexpectedException != null)
+                throw new Failure("Exception was thrown during ProcessWaiterThread work: "
+                        + unexpectedException, unexpectedException);
+        }
+    }
+
+    public ProcessExecutor(String cmdLine, long timeout) {
+        this.cmdLine = new String[]{cmdLine};
+        this.timeout = timeout;
+    }
+
+    public ProcessExecutor(String cmdLine, long timeout, String outputPrefix) {
+        this(cmdLine, timeout);
+        this.printProcessOutput = true;
+        this.processOutputPrefix = outputPrefix;
+    }
+
+    public void startProcess() throws IOException {
+        if (cmdLine.length == 1)
+            startedProcess = Runtime.getRuntime().exec(cmdLine[0]);
+        else
+            startedProcess = Runtime.getRuntime().exec(cmdLine);
+
+        expectedFinishTime = System.currentTimeMillis() + timeout;
+
+        outReader = new InputStreamReaderThread(startedProcess.getInputStream(),
+                processOutputPrefix == null ? "" : processOutputPrefix + " (stdout): ");
+        errReader = new InputStreamReaderThread(startedProcess.getErrorStream(),
+                processOutputPrefix == null ? "" : processOutputPrefix + " (stderr): ");
+
+        outReader.start();
+        errReader.start();
+
+        processWaiter = new ProcessWaiterThread(startedProcess, outReader, errReader);
+        processWaiter.start();
+    }
+
+
+    public void waitForProcess() throws InterruptedException {
+        synchronized (processWaiter) {
+            while ((System.currentTimeMillis() < expectedFinishTime) && !executionCompleted) {
+                processWaiter.wait(expectedFinishTime - System.currentTimeMillis());
+            }
+        }
+
+        if (!executionCompleted) {
+            destroyProcessAndWaitThreads();
+
+            executionCompleted = true;
+
+            throw new Failure("Execution timed out (timeout: " + timeout + "ms)");
+        }
+    }
+
+    private void destroyProcessAndWaitThreads() {
+        outReader.streamWasAbruptlyClosed(true);
+        errReader.streamWasAbruptlyClosed(true);
+
+        processWaiter.interrupt();
+        startedProcess.destroy();
+
+        try {
+            outReader.join();
+            errReader.join();
+            processWaiter.join();
+
+            outReader.checkStatus();
+            errReader.checkStatus();
+            processWaiter.checkStatus();
+        } catch (InterruptedException e) {
+            throw new Failure("Unexpected InterruptedException", e);
+        }
+    }
+
+    private void checkProcessState() {
+        if (!executionCompleted)
+            throw new IllegalStateException("Process didn't finish execution");
+    }
+
+    public void destroyProcess() {
+        if (executionCompleted)
+            return;
+
+        destroyProcessAndWaitThreads();
+    }
+
+    public long pid() {
+        return startedProcess.pid();
+    }
+
+    public int getExitCode() {
+        checkProcessState();
+
+        return exitCode;
+    }
+
+    public List<String> getProcessOut() {
+        checkProcessState();
+
+        return outReader.output;
+    }
+
+    public List<String> getProcessErr() {
+        checkProcessState();
+
+        return errReader.output;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/TargetApplicationWaitingAgents.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import nsk.share.*;
+import nsk.share.jpda.SocketIOPipe;
+
+import java.util.*;
+
+/*
+Class TargetApplicationWaitingAgents is part of the framework used in the AttachOnDemand tests
+(tests against Attach API, API from package com.sun.tools.attach).
+
+Attach API allows to load so called 'agents' in the running VM. In terms of this framework
+application running in the VM where agent is loaded to is called 'target application'.
+
+TargetApplicationWaitingAgents is base class for target applications used in the AttachOnDemand tests
+(also TargetApplicationWaitingAgents can be used without modifications in tests where target
+application shouldn't execute some test-specific actions).
+
+AttachOnDemand tests requires synchronization between test agents and target application:
+    - before target application can start to execute test-specific actions it
+    should wait when all tests agents will be loaded
+
+    - target application shouldn't finish until all agents finish their work
+
+TargetApplicationWaitingAgents incapsulates actions common for all target applications. TargetApplicationWaitingAgents
+provides 2 methods: 'agentLoaded' and 'agentFinished', test agents use these methods to notify
+target application about its status. When target application based on the TargetApplicationWaitingAgents
+starts it first waits when all test agents will be loaded (number of expected test agents is
+passed via parameter -agentsNumber). After this target application executes test-specific actions,
+waits when all test agents will finish, checks agent's status (passed of failed) and
+finishes.
+
+In most cases test target applications should override only method 'targetApplicationActions' and
+its 'main' method should contain only call of the method 'TargetApplicationWaitingAgents.runTargetApplication'.
+
+Typical target application class looks like this:
+
+public class targetExample extends TargetApplicationWaitingAgents {
+
+    protected void targetApplicationActions() {
+        // do test-specific actions
+    }
+
+    public static void main(String[] args) {
+        new targetExample().runTargetApplication(args);
+    }
+}
+*/
+public class TargetApplicationWaitingAgents {
+
+    private volatile static boolean testFailed = false;
+
+    private static long AGENTS_CONNECTION_TIMEOUT = 5 * 60 * 1000; // 5 min
+
+    private static long AGENTS_FINISHING_TIMEOUT = 5 * 60 * 1000; // 5 min
+
+    private static boolean allAgentsAttached;
+
+    private static List<String> attachedAgents = new ArrayList<String>();
+
+    private static boolean allAgentsFinished;
+
+    private static List<String> finishedAgents = new ArrayList<String>();
+
+    private static boolean targetApplicationInitialized;
+
+    static protected AODTargetArgParser argParser;
+
+    protected static Log log;
+
+    static private Object monitor = new Object();
+
+    /*
+     * Methods
+     *  - agentLoaded(String agentName) and
+     *  - agentFinished(String agentName, boolean finishedSuccessfully)
+     *  are called from test agents to notify target application about its status
+     */
+
+    public static void agentLoaded(String agentName) {
+        synchronized (monitor) {
+            if (!targetApplicationInitialized)
+                waitForTargetApplicationInitialization();
+
+            // check test logic
+            if (attachedAgents.contains(agentName)) {
+                setStatusFailed("Agent '" + agentName + "' already attached");
+
+                // let TargetApplication complete execution in case of error
+                allAgentsAttached = true;
+                monitor.notifyAll();
+
+                throw new TestBug("Agent '" + agentName + "' calls method 'agentLoaded' more than 1 time");
+            } else {
+                attachedAgents.add(agentName);
+
+                log.display("Agent '" + agentName + "' was loaded");
+
+                allAgentsAttached = (attachedAgents.size() == argParser.getExpectedAgentsNumber());
+
+                if (allAgentsAttached)
+                    monitor.notifyAll();
+
+                // check test logic
+                if (attachedAgents.size() > argParser.getExpectedAgentsNumber()) {
+                    setStatusFailed("Unexpected agent attached (expected agents number: " +
+                            argParser.getExpectedAgentsNumber() +
+                            ", but " + attachedAgents.size() + " agents were loaded)");
+
+                    throw new TestBug("More agents attached than it was expected" +
+                                " (expected: " + argParser.getExpectedAgentsNumber() +
+                                ", attached: " + attachedAgents.size() + ")");
+                }
+            }
+        }
+    }
+
+    public static void agentFinished(String agentName, boolean finishedSuccessfully) {
+        synchronized (monitor) {
+            // check test logic
+            if (!targetApplicationInitialized)
+                throw new TestBug("Method 'agentFinished' was called before TargetApplication was initialized");
+
+            boolean algorithmError = false;
+            String errorMessage = "Test algorithm error:";
+
+            if (!attachedAgents.contains(agentName)) {
+                algorithmError = true;
+                errorMessage += " agent '" + agentName + "' didn't call method 'agentLoaded';";
+                log.complain(errorMessage);
+            }
+
+            if (finishedAgents.contains(agentName)) {
+                algorithmError = true;
+                errorMessage += " agent '" + agentName + "' already called method 'agentFinished';";
+                log.complain(errorMessage);
+            }
+
+            if (algorithmError) {
+                // let TargetApplication complete execution in case of error
+                allAgentsFinished = true;
+                monitor.notifyAll();
+
+                throw new TestBug(errorMessage);
+            } else {
+                finishedAgents.add(agentName);
+
+                log.display("Agent '" + agentName + "' finished execution (finishedSuccessfully: " + finishedSuccessfully + ")");
+
+                if (!finishedSuccessfully)
+                    setStatusFailed("Agent '" + agentName + " finished with error status");
+
+                allAgentsFinished = (finishedAgents.size() == argParser.getExpectedAgentsNumber());
+
+                if (allAgentsAttached)
+                    monitor.notifyAll();
+            }
+        }
+    }
+
+    /*
+     * This method is called from the method 'agentLoaded' in case
+     * when target application isn't initialized yet at the moment
+     * when agent is connecting
+     */
+    static private void waitForTargetApplicationInitialization() {
+        synchronized (monitor) {
+            while (!targetApplicationInitialized) {
+                try {
+                    monitor.wait();
+                } catch (InterruptedException e) {
+                    // should never happen
+                    exitAsFailed(e);
+                }
+            }
+        }
+    }
+
+    /*
+     * This method is introduced to let subclasses to create its own parsers
+     */
+    protected AODTargetArgParser createArgParser(String[] args) {
+        return new AODTargetArgParser(args);
+    }
+
+    /*
+     * Target application initialization
+     */
+    private void initTargetApplication(String[] args) {
+        synchronized (monitor) {
+            if (targetApplicationInitialized)
+                throw new TestBug("TargetApplication already initialized");
+
+            log = new Log(System.out, true);
+
+            argParser = createArgParser(args);
+
+            // test-specific initialization
+            init(args);
+
+            targetApplicationInitialized = true;
+            monitor.notifyAll();
+        }
+    }
+
+    static private void waitAgentsConnection() {
+        synchronized (monitor) {
+            long waitFinishTime = System.currentTimeMillis() + AGENTS_CONNECTION_TIMEOUT;
+
+            while (!allAgentsAttached && (System.currentTimeMillis() < waitFinishTime)) {
+                try {
+                    monitor.wait(AGENTS_CONNECTION_TIMEOUT);
+                } catch (InterruptedException e) {
+                    // should never happen
+                    exitAsFailed(e);
+                }
+            }
+        }
+
+        if (!allAgentsAttached) {
+            exitAsFailed("Agents didn't attach in " + AGENTS_CONNECTION_TIMEOUT + "ms, stop execution " +
+                    "(expected agents number: " + argParser.getExpectedAgentsNumber() +
+                    ", attached agents number: " + attachedAgents.size() + ")");
+        }
+    }
+
+    static private void waitAgentsFinishing() {
+        synchronized (monitor) {
+            long waitFinishTime = System.currentTimeMillis() + AGENTS_FINISHING_TIMEOUT;
+
+            while (!allAgentsFinished && (System.currentTimeMillis() < waitFinishTime)) {
+                try {
+                    monitor.wait(AGENTS_FINISHING_TIMEOUT);
+                } catch (InterruptedException e) {
+                    // should never happen
+                    exitAsFailed(e);
+                }
+            }
+        }
+
+        if (!allAgentsFinished)
+            exitAsFailed("Agents didn't finish in " + AGENTS_FINISHING_TIMEOUT + "ms, stop execution " +
+                        "(attached agents number: " + attachedAgents.size() +
+                        ", finished agents number: " + finishedAgents.size() + ")");
+    }
+
+    /*
+     * Print error message and set failed status, but don't exit
+     */
+
+    static public void setStatusFailed(String message) {
+        testFailed = true;
+        log.complain(message);
+    }
+
+    static public void setStatusFailed(Throwable t) {
+        testFailed = true;
+        log.complain("Unexpected exception: " + t);
+        t.printStackTrace(log.getOutStream());
+    }
+
+    /*
+     * Print error message and exit with fail status
+     */
+    static protected void exitAsFailed(String errorMessage) {
+        try {
+            log.complain(errorMessage);
+            log.complain("Stop execution");
+        } finally {
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+    }
+
+    /*
+     * Print error message and exit with fail status
+     */
+    static protected void exitAsFailed(Throwable t) {
+        try {
+            log.complain("Unexpected exception was thrown during TargetApplication execution: " + t);
+            t.printStackTrace(log.getOutStream());
+            log.display("Stop execution");
+        } finally {
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+    }
+
+    /*
+     * Following 3 methods can be overridden in subclasses:
+     *
+     *  - init(String[] args)
+     *
+     *  - targetApplicationActions()
+     *
+     *  - afterAgentsFinished()
+     */
+
+    /*
+     * Test-specific initialization
+     */
+    protected void init(String[] args) {
+
+    }
+
+    protected void targetApplicationActions() throws Throwable {
+        // do nothing by default
+    }
+
+    protected void afterAgentsFinished() {
+        // do nothing by default
+    }
+
+    public final void runTargetApplication(String[] args) {
+        initTargetApplication(args);
+
+        SocketIOPipe pipe = null;
+
+        try {
+            if (argParser.getPort() > 0) {
+                /*
+                 * When target application initialized send signal to AODTestRunner
+                 */
+                pipe = SocketIOPipe.createClientIOPipe(log, "localhost", argParser.getPort(), 0);
+                log.display("Sending signal '" + AODTestRunner.SIGNAL_READY_FOR_ATTACH + "'");
+                pipe.println(AODTestRunner.SIGNAL_READY_FOR_ATTACH);
+            }
+
+            log.display("Waiting for agents connection");
+            waitAgentsConnection();
+            log.display("All expected agents connected");
+
+            try {
+                targetApplicationActions();
+            } catch (Throwable e) {
+                /*
+                 * If something goes wrong during test execution it is better
+                 * to exit without waiting for agents
+                 */
+
+                if (pipe != null)
+                    pipe.close();
+
+                exitAsFailed(e);
+            }
+
+            log.display("Waiting for agents finishing");
+            waitAgentsFinishing();
+            log.display("All agents finished execution");
+
+            afterAgentsFinished();
+
+            if (pipe != null) {
+                /*
+                 * Don't finish execution until AODTestRunner attached agents
+                 */
+                String signal = pipe.readln();
+                log.display("Signal received: '" + signal + "'");
+                if ((signal == null) || !signal.equals(AODTestRunner.SIGNAL_FINISH))
+                    throw new TestBug("Unexpected AODTestRunner signal: '" + signal + "'");
+
+                if (testFailed) {
+                    if (pipe != null)
+                        pipe.close();
+
+                    exitAsFailed("Error happened during TargetApplication execution (see error messages for details)");
+                } else {
+                    log.display("Test passed");
+                }
+            }
+        } finally {
+            if (pipe != null)
+                pipe.close();
+        }
+    }
+
+    public static void main(String[] args) {
+        new TargetApplicationWaitingAgents().runTargetApplication(args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/Utils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.aod;
+
+import java.io.File;
+
+import nsk.share.*;
+
+public class Utils {
+
+    // prevent class instantiation
+    private Utils() {
+    }
+
+    public static final long JPS_WORK_TIMEOUT = 60000; // 1 min
+
+    /**
+     * Find id of VM with certain value of property key.  Method findVMIdUsingJPS
+     * runs 'jps -v' and seeks in jps output line containing this unique string,
+     * discovered string should also contain VM id.
+     *
+     * @param jdkPath - path to jdk
+     * @param key     - name of property
+     * @param value   - value of property
+     * @return VM id
+     */
+    public static String findVMIdUsingJPS(String jdkPath, String key, String value) {
+        try {
+            if (value == null) {
+                return null;
+            }
+            String idString = key + "=" + value;
+            String jpsPath = jdkPath + File.separator + "bin" + File.separator + "jps";
+
+            while (true) {
+                ProcessExecutor executor = new ProcessExecutor(jpsPath + " -v", JPS_WORK_TIMEOUT, "jps -v");
+                executor.startProcess();
+                executor.waitForProcess();
+
+                if (executor.getExitCode() != 0) {
+                    throw new Failure("jps finished with non-zero code " + executor.getExitCode());
+                }
+
+                for (String jpsOutLine : executor.getProcessOut()) {
+                    if (jpsOutLine.contains(idString)) {
+                        if (jpsOutLine.indexOf(' ') < 0)
+                            throw new Failure("Unexpected format of the jps output '" + jpsOutLine + " (line doesn't contain space)");
+
+                        return jpsOutLine.substring(0, jpsOutLine.indexOf(' '));
+                    }
+                }
+                Thread.sleep(100);
+            }
+        } catch (Failure f) {
+            throw f;
+        } catch (Throwable t) {
+            throw new Failure("Unexpected exception during jps execution: " + t, t);
+        }
+    }
+
+    public static String findCurrentVMIdUsingJPS(String jdkPath) {
+        /*
+         * VM should be run with special property which allows to find VM id using jps
+         * (see comments for method Utils.findVMIdUsingJPS)
+         */
+        String applicationId = System.getProperty(AODTestRunner.targetAppIdProperty);
+        if (applicationId == null)
+            throw new TestBug("Property '" + AODTestRunner.targetAppIdProperty + "' isn't defined");
+
+        String targetVMId = Utils.findVMIdUsingJPS(jdkPath, AODTestRunner.targetAppIdProperty, applicationId);
+
+        return targetVMId;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <jni.h>
+#include <jni_tools.h>
+#include <nsk_tools.h>
+#include <aod.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static volatile int internalError = 0;
+
+/*
+ * This function can be used to inform AOD framework that some non critical for test logic
+ * error happened inside shared function (e.g. JVMTI Deallocate failed).
+ *
+ * If this function was called status of all finishing AOD agents is changed to failed.
+ */
+
+void nsk_aod_internal_error() {
+    NSK_COMPLAIN0("WARNING: some error happened inside common function, see log for details\n");
+    internalError = 1;
+}
+
+void nsk_free_options(Options* options) {
+  if (options != NULL) {
+    int i;
+    for (i = 0; i < NSK_AOD_MAX_OPTIONS; i++) {
+      if (options->names[i] != NULL) {
+        free(options->names[i]);
+      }
+      if (options->values[i] != NULL) {
+        free(options->values[i]);
+      }
+    }
+    free(options);
+  }
+}
+/*
+ * Work with agent options
+ */
+
+/*
+ * Parse options and create structure Options
+ */
+static Options* nsk_aod_createOptionsObject(char* optionsString) {
+    int i = 0;
+    Options* options;
+    char* name;
+    char* value;
+    char* sep;
+
+    if (optionsString == NULL) {
+      NSK_COMPLAIN0("options were not passed to the native agent\n");
+      return NULL;
+    }
+    options = (Options*) malloc(sizeof(Options));
+    memset(options, 0, sizeof(Options));
+    options->size = 0;
+    name = optionsString;
+    while (name != NULL && i < NSK_AOD_MAX_OPTIONS) {
+      sep = strchr(name, '=');
+      if (sep == NULL) { // name not found
+        NSK_COMPLAIN1("Invalid options format: '%s'\n", optionsString);
+        nsk_free_options(options);
+        return NULL;
+      }
+      *sep = '\0';
+      options->names[i] =  strdup(name);
+      value = sep + 1;
+      if (*value == '\0') { // value not found
+        NSK_COMPLAIN1("Option '%s' is empty\n", options->names[i]);
+        nsk_free_options(options);
+        return NULL;
+      }
+      sep = strchr(value, ' ');
+      if (sep != NULL) {
+        *sep = '\0';
+        name = sep + 1;
+      } else {
+        name = strchr(value, '\0');
+      }
+      options->values[i] = strdup(value);
+      i++;
+
+      if (*name == '\0') {
+        name = NULL;
+      }
+    }
+    if (name != NULL) {
+      NSK_COMPLAIN1("WARNING: not all options were parsed, only %d options can be specified\n",
+                    NSK_AOD_MAX_OPTIONS);
+    }
+    options->size = i;
+    return options;
+}
+
+Options* nsk_aod_createOptions(char* optionsString) {
+    Options* options;
+
+    if (!NSK_VERIFY((options = (Options*) nsk_aod_createOptionsObject(optionsString)) != NULL))
+        return NULL;
+
+    if (!NSK_VERIFY(nsk_aod_optionSpecified(options, NSK_AOD_AGENT_NAME_OPTION))) {
+        NSK_COMPLAIN0("Agent name wasn't specified\n");
+        return NULL;
+    }
+
+    /*
+     * verbose mode is true by default
+     */
+    nsk_setVerboseMode(NSK_TRUE);
+
+    if (nsk_aod_optionSpecified(options, NSK_AOD_VERBOSE_OPTION)) {
+        if (strcmp(nsk_aod_getOptionValue(options, NSK_AOD_VERBOSE_OPTION), "false") == 0)
+            nsk_setVerboseMode(NSK_FALSE);
+    }
+
+    return options;
+}
+
+const char* nsk_aod_getOptionValue(Options* options, const char* option) {
+    int i;
+
+    if (!NSK_VERIFY(options != NULL)) {
+        NSK_COMPLAIN0("Options NULL\n");
+        return NULL;
+    }
+
+    for(i = 0; i < options->size; i++) {
+        if (strcmp(option, options->names[i]) == 0) {
+            return options->values[i];
+        }
+    }
+
+    NSK_COMPLAIN1("Option '%s' isn't defined\n", option);
+
+    return NULL;
+}
+
+int nsk_aod_optionSpecified(Options* options, const char* option) {
+    int i;
+
+    if (!NSK_VERIFY(options != NULL)) {
+        NSK_COMPLAIN0("Options NULL\n");
+        return NSK_FALSE;
+    }
+
+    for(i = 0; i < options->size; i++) {
+        if (strcmp(option, options->names[i]) == 0) {
+            return NSK_TRUE;
+        }
+    }
+
+    return NSK_FALSE;
+}
+
+/*
+ * Agent synchronization with target application
+ */
+
+static const char* TARGET_APP_CLASS_NAME = "nsk/share/aod/TargetApplicationWaitingAgents";
+
+static const char* AGENT_LOADED_METHOD_NAME = "agentLoaded";
+static const char* AGENT_LOADED_METHOD_SIGNATURE = "(Ljava/lang/String;)V";
+
+static const char* AGENT_FINISHED_METHOD_NAME = "agentFinished";
+static const char* AGENT_FINISHED_METHOD_SIGNATURE = "(Ljava/lang/String;Z)V";
+
+static jclass targetAppClass = NULL;
+static jmethodID agentLoadedMethod = NULL;
+static jmethodID agentFinishedMethod = NULL;
+
+// this function is used to notify target application that native agent has been loaded
+int nsk_aod_agentLoaded(JNIEnv* jni, const char* agentName) {
+    jstring agentNameString;
+
+    NSK_DISPLAY1("Agent %s is loaded\n", agentName);
+
+    if (targetAppClass == NULL) {
+        /*
+         * FindClass returns local reference, to cache reference to target application class
+         * global reference should be created
+         */
+        jclass localTargetAppClass;
+        if (!NSK_JNI_VERIFY(jni, (localTargetAppClass =
+            NSK_CPP_STUB2(FindClass, jni, TARGET_APP_CLASS_NAME)) != NULL)) {
+            return NSK_FALSE;
+        }
+
+        if (!NSK_JNI_VERIFY(jni, (targetAppClass =
+            NSK_CPP_STUB2(NewGlobalRef, jni, localTargetAppClass)) != NULL)) {
+            return NSK_FALSE;
+        }
+    }
+
+    if (agentLoadedMethod == NULL) {
+        if (!NSK_JNI_VERIFY(jni, (agentLoadedMethod =
+            NSK_CPP_STUB4(GetStaticMethodID, jni, targetAppClass,
+                    AGENT_LOADED_METHOD_NAME, AGENT_LOADED_METHOD_SIGNATURE)) != NULL))
+            return NSK_FALSE;
+    }
+
+    if (!NSK_JNI_VERIFY(jni, (agentNameString =
+        NSK_CPP_STUB2(NewStringUTF, jni, agentName)) != NULL))
+        return NSK_FALSE;
+
+    NSK_CPP_STUB4(CallStaticVoidMethod, jni, targetAppClass, agentLoadedMethod, agentNameString);
+
+    return NSK_TRUE;
+}
+
+// this function is used to notify target application that native agent has been finished execution
+int nsk_aod_agentFinished(JNIEnv* jni, const char* agentName, int success) {
+    jstring agentNameString;
+
+    if (!targetAppClass) {
+        NSK_COMPLAIN1("%s: TEST LOGIC ERROR: method 'agentFinished' was called before "\
+                "targetAppClass was initialized\n", agentName);
+        return NSK_FALSE;
+    }
+
+    if (internalError && success) {
+        success = 0;
+        NSK_COMPLAIN1("Status of agent '%s' is 'passed', but some error happened during test execution "\
+                "(see log for details), change agent status to 'failed'\n",
+                agentName);
+    }
+
+    NSK_DISPLAY2("Agent %s finished (success: %d)\n", agentName, success);
+
+    if (agentFinishedMethod == NULL) {
+        if (!NSK_JNI_VERIFY(jni, (agentFinishedMethod =
+            NSK_CPP_STUB4(GetStaticMethodID, jni, targetAppClass,
+                    AGENT_FINISHED_METHOD_NAME, AGENT_FINISHED_METHOD_SIGNATURE)) != NULL))
+            return NSK_FALSE;
+    }
+
+    if (!NSK_JNI_VERIFY(jni, (agentNameString = NSK_CPP_STUB2(NewStringUTF, jni, agentName)) != NULL))
+        return NSK_FALSE;
+
+    NSK_CPP_STUB5(CallStaticVoidMethod, jni, targetAppClass,
+            agentFinishedMethod, agentNameString, success ? JNI_TRUE : JNI_FALSE);
+
+    return NSK_TRUE;
+}
+
+/*
+ * Auxiliary functions
+ */
+
+// JNI env creation
+
+JNIEnv* nsk_aod_createJNIEnv(JavaVM* vm) {
+    JNIEnv* jni;
+    NSK_CPP_STUB3(GetEnv, vm, (void**)&jni, JNI_VERSION_1_2);
+
+    NSK_VERIFY(jni != NULL);
+
+    return jni;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/aod.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifndef NSK_SHARE_AOD_H
+#define NSK_SHARE_AOD_H
+
+#include <jni.h>
+#include <jni_tools.h>
+#include <nsk_tools.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This function can be used to inform AOD framework that some non-critical for test logic
+ * error happened inside shared function (e.g. JVMTI Deallocate failed).
+ *
+ * If this function was called status of all finishing AOD agents is changed to failed.
+ */
+
+void nsk_aod_internal_error();
+
+/*
+ * Work with agent options
+ */
+
+#define NSK_AOD_MAX_OPTIONS 10
+
+#define NSK_AOD_AGENT_NAME_OPTION "-agentName"
+#define NSK_AOD_VERBOSE_OPTION "-verbose"
+
+typedef struct {
+    char* names[NSK_AOD_MAX_OPTIONS];
+    char* values[NSK_AOD_MAX_OPTIONS];
+    int size;
+} Options;
+
+Options* nsk_aod_createOptions(char* optionsString);
+
+const char* nsk_aod_getOptionValue(Options* options, const char* option);
+
+int nsk_aod_optionSpecified(Options* options, const char* option);
+
+/*
+ * Agent synchronization with target application
+ */
+
+// this function is used to notify target application that native agent has been loaded
+int nsk_aod_agentLoaded(JNIEnv* jni, const char* agentName);
+
+// this function is used to notify target application that native agent has been finished execution
+int nsk_aod_agentFinished(JNIEnv* jni, const char* agentName, int success);
+
+
+// JNI env creation
+
+JNIEnv* nsk_aod_createJNIEnv(JavaVM* vm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* END OF NSK_SHARE_AOD_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/classload/ClassPathNonDelegatingClassLoader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.classload;
+
+import java.io.*;
+import java.util.*;
+
+import nsk.share.FileUtils;
+
+/**
+ * Custom classloader that does not delegate to it's parent.
+ *
+ * It can load classes from classpath that have name containing
+ * "Class" (any package).
+ */
+public class ClassPathNonDelegatingClassLoader extends ClassLoader {
+        private String [] classPath;
+
+        public ClassPathNonDelegatingClassLoader() {
+                classPath = System.getProperty("java.class.path").split(File.pathSeparator);
+        }
+
+        public synchronized Class loadClass(String name, boolean resolve)
+                throws ClassNotFoundException {
+                Class c = findLoadedClass(name);
+                if (c != null) {
+                        System.out.println("Found class: " + name);
+                        return c;
+                }
+                if (name.contains("Class")) {
+                        String newName = name.replace('.', '/');
+                        return loadClassFromFile(name, newName + ".class", resolve);
+                } else {
+                        return findSystemClass(name);
+                }
+        }
+
+        private Class loadClassFromFile(String name, String fname, boolean resolve)
+                throws ClassNotFoundException {
+                try {
+                        File target = new File("");
+
+                        for(int i = 0; i < classPath.length; ++i) {
+                                target = new File(classPath[i] + File.separator + fname);
+                                if (target.exists())
+                                        break;
+                        }
+                        if (!target.exists())
+                                throw new java.io.FileNotFoundException();
+                        byte[] buffer = FileUtils.readFile(target);
+                        Class c = defineClass(name, buffer, 0, buffer.length);
+                        if (resolve)
+                                resolveClass(c);
+                        return c;
+                } catch (IOException e) {
+                        throw new ClassNotFoundException("Exception while reading classfile data", e);
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/classload/GeneratingClassLoader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.classload;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.*;
+
+/**
+ * Classloader that generates classes on the fly.
+ *
+ * This classloader can load classes with name starting with 'Class'.
+ * It will use nsk.share.classload.TemplateClass as template and will
+ * replace class name in the bytecode of template class. It can be used
+ * for example to detect memory leaks in class loading or to quickly
+ * fill PermGen.
+ */
+public class GeneratingClassLoader extends ClassLoader {
+        public static final String DEFAULT_CLASSNAME = TemplateClass.class.getName();
+        public static final String PREFIX = "Class";
+
+        private final String [] classPath;
+        private byte[] bytecode;
+        private int[] offsets;
+        private final String encoding = "UTF8";
+        private final String templateClassName;
+        private final byte[] templateClassNameBytes;
+
+        /**
+         * Create generating class loader that will use class file
+         * for given class from classpath as template.
+         */
+        public GeneratingClassLoader(String templateClassName) {
+                this.templateClassName = templateClassName;
+                classPath = System.getProperty("java.class.path").split(File.pathSeparator);
+                try {
+                        templateClassNameBytes = templateClassName.getBytes(encoding);
+                } catch (UnsupportedEncodingException e) {
+                        throw new TestBug(e);
+                }
+        }
+
+        /**
+         * Create generating class loader that will use class file
+         * for nsk.share.classload.TemplateClass as template.
+         */
+        public GeneratingClassLoader() {
+                this("nsk.share.classload.TemplateClass");
+        }
+
+        public int getNameLength() {
+                return templateClassName.length();
+        }
+
+        public String getPrefix() {
+                return PREFIX;
+        }
+
+        public String getClassName(int number) {
+                StringBuffer sb = new StringBuffer();
+                sb.append(PREFIX);
+                sb.append(number);
+                int n = templateClassName.length() - sb.length();
+                for (int i = 0; i < n; ++i)
+                        sb.append("_");
+                return sb.toString();
+        }
+
+        public synchronized Class loadClass(String name) throws ClassNotFoundException {
+                return loadClass(name, false);
+        }
+
+        public synchronized Class loadClass(String name, boolean resolve)
+                throws ClassNotFoundException {
+                Class c = findLoadedClass(name);
+                if (c != null)
+                        return c;
+                if (!name.startsWith(PREFIX))
+                        return super.loadClass(name, resolve);
+                if (name.length() != templateClassName.length())
+                        throw new ClassNotFoundException("Only can load classes with name.length() = " + getNameLength() + " got: '" + name + "' length: " + name.length());
+                byte[] bytecode = getPatchedByteCode(name);
+                c = defineClass(name, bytecode, 0, bytecode.length);
+                if (resolve)
+                        resolveClass(c);
+                return c;
+        }
+
+        private byte[] getPatchedByteCode(String name) throws ClassNotFoundException {
+                try {
+                        byte[] bytecode = getByteCode();
+                        String fname = name.replace(".", File.separator);
+                        byte[] replaceBytes = fname.getBytes(encoding);
+                        for (int offset : offsets) {
+                                for (int i = 0; i < replaceBytes.length; ++i)
+                                        bytecode[offset + i] = replaceBytes[i];
+                        }
+                        return bytecode;
+                } catch (UnsupportedEncodingException e) {
+                        throw new TestBug(e);
+                } catch (IOException e) {
+                        throw new TestBug(e);
+                }
+        }
+
+        private byte[] getByteCode() throws ClassNotFoundException {
+                if (bytecode == null)
+                        readByteCode();
+                if (offsets == null) {
+                        getOffsets(bytecode);
+                        if (offsets == null)
+                                throw new TestBug("Class name not found in template class file");
+                }
+                return (byte[]) bytecode.clone();
+        }
+
+        private void readByteCode() throws ClassNotFoundException {
+                String fname = templateClassName.replace(".", File.separator) + ".class";
+                File target = null;
+                for (int i = 0; i < classPath.length; ++i) {
+                        target = new File(classPath[i] + File.separator + fname);
+                        if (target.exists())
+                                break;
+                }
+
+                if (target == null || !target.exists())
+                        throw new ClassNotFoundException("File not found: " + target);
+                try {
+                        bytecode = FileUtils.readFile(target);
+                } catch (IOException e) {
+                        throw new ClassNotFoundException(templateClassName, e);
+                }
+        }
+
+        private void getOffsets(byte[] bytecode) {
+                List<Integer> offsets = new ArrayList<Integer>();
+                if (this.offsets == null) {
+                        String pname = templateClassName.replace(".", "/");
+                        try {
+                                byte[] pnameb = pname.getBytes(encoding);
+                                int i = 0;
+                                while (true) {
+                                        while (i < bytecode.length) {
+                                                int j = 0;
+                                                while (j < pnameb.length && bytecode[i + j] == pnameb[j])
+                                                        ++j;
+                                                if (j == pnameb.length)
+                                                        break;
+                                                i++;
+                                        }
+                                        if (i == bytecode.length)
+                                                break;
+                                        offsets.add(new Integer(i));
+                                        i++;
+                                }
+                        } catch (UnsupportedEncodingException e) {
+                                throw new TestBug(e);
+                        }
+                        this.offsets = new int[offsets.size()];
+                        for (int i = 0; i < offsets.size(); ++i)
+                                this.offsets[i] = offsets.get(i).intValue();
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/classload/TemplateClass.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.classload;
+
+public class TemplateClass {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Algorithms.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.*;
+import nsk.share.gc.gp.*;
+import nsk.share.test.ExecutionController;
+
+/**
+ * <tt>Algorithms</tt> class collects main algorithms that are used in
+ * GC testing.
+ */
+public class Algorithms {
+        /** Number of threads that one CPU can manage. */
+        public final static long THREADS_MANAGED_BY_ONE_CPU = 100;
+
+        /** Number of threads that one block of memory can manage. */
+        public final static long THREADS_MANAGED_BY_ONE_BLOCK = 200;
+
+        /** Default maximum number of elements in array. */
+        public final static int MAX_ARRAY_SIZE = 65535;
+
+        // Block of memory is 64M
+        private final static long BLOCK_SIZE = 64 * 1024 * 1024; // 64M
+
+        // Minimal memory chunk size to eat
+        private final static int MIN_MEMORY_CHUNK = 512; // Bytes
+
+        // Number of attempts to print a string. Print may fail because of
+        // OutOfMemoryError, so this constat specifies the number of attemts
+        // to print despite of OOME.
+        private final static int ATTEMPTS_TO_PRINT = 3;
+
+        // This object stores any Failure that is thrown in Gourmand class
+        // and used in eatMemory(int) method
+        private static Failure failure = null;
+
+        // This object is intended for wait()
+        private static Object object = new Object();
+
+        /**
+         * Default constructor.
+         */
+        private Algorithms() {}
+
+        /**
+         * Stresses memory by allocating arrays of bytes. The method allocates
+         * objects in the same thread and does not invoke GC explicitly by
+         * calling <tt>System.gc()</tt>.
+         * <p>
+         *
+         * Note that this method can throw Failure if any exception
+         * is thrown while eating memory. To avoid OOM while allocating
+         * exception we preallocate it before the lunch starts. It means
+         * that exception stack trace does not correspond to the place
+         * where exception is thrown, but points at start of the method.
+         *
+         * This method uses nsk.share.test.Stresser class to control
+         * it's execution. Consumed number of iterations depends on
+         * available memory.
+         *
+         * @throws <tt>nsk.share.Failure</tt> if any unexpected exception is
+         * thrown during allocating of the objects.
+         *
+         * @see nsk.share.test.Stresser
+         */
+        public static void eatMemory(ExecutionController stresser) {
+            GarbageUtils.eatMemory(stresser, 50, MIN_MEMORY_CHUNK, 2);
+        }
+
+        /**
+         * Calculates and returns recomended number of threads to start in the
+         * particular machine (with particular amount of memory and number of CPUs).
+         * The returned value is minimum of two values:
+         * {@link #THREADS_MANAGED_BY_ONE_CPU} * (number of processors) and
+         * {@link #THREADS_MANAGED_BY_ONE_BLOCK} * (number of blocks of the memory).
+         *
+         * @return recomended number of threads to start.
+         *
+         */
+        public static int getThreadsCount() {
+                Runtime runtime = Runtime.getRuntime();
+                int processors = runtime.availableProcessors();
+                long maxMemory = runtime.maxMemory();
+                long blocks = Math.round((double) maxMemory / BLOCK_SIZE);
+
+                return (int) Math.min(THREADS_MANAGED_BY_ONE_CPU * processors,
+                                THREADS_MANAGED_BY_ONE_BLOCK * blocks);
+        }
+
+        /**
+         * Returns the number of processors available to the Java virtual machine.
+         *
+         * @return number of processors available to the Java virtual machine.
+         *
+         * @see Runtime#availableProcessors
+         *
+         */
+        public static int availableProcessors() {
+                Runtime runtime = Runtime.getRuntime();
+                return runtime.availableProcessors();
+        }
+
+        /**
+         * Makes a few attempts to print the string into specified PrintStream.
+         * If <code>PrintStream.println(String)</code> throws OutOfMemoryError,
+         * the method waits for a few milliseconds and repeats the attempt.
+         *
+         * @param out PrintStream to print the string.
+         * @param s the string to print.
+         */
+        public static void tryToPrintln(PrintStream out, String s) {
+                for (int i = 0; i < ATTEMPTS_TO_PRINT; i++) {
+                        try {
+                                out.println(s);
+
+                                // The string is printed into the PrintStream
+                                return;
+                        } catch (OutOfMemoryError e) {
+
+                                // Catch the error and wait for a while
+                                synchronized(object) {
+                                        try {
+                                                object.wait(500);
+                                        } catch (InterruptedException ie) {
+
+                                                // Ignore the exception
+                                        }
+                                } // synchronized
+                        }
+                }
+        } // tryToPrintln()
+
+        /**
+         * Makes a few attempts to print each stack trace of <code>Throwable</code>
+         * into specified PrintStream. If <code>PrintStream.println(String)</code>
+         * throws OutOfMemoryError, the method waits for a few milliseconds and
+         * repeats the attempt.
+         *
+         * @param out PrintStream to print the string.
+         * @param t the throwable to print.
+         *
+         * @see #tryToPrintln
+         */
+        public static void tryToPrintStack(PrintStream out, Throwable t) {
+                StackTraceElement[] trace = t.getStackTrace();
+
+                for (int i = 0; i < trace.length; i++) {
+                        for (int j = 0; j < ATTEMPTS_TO_PRINT; j++) {
+                                try {
+                                        out.println(trace[i].toString());
+
+                                        // The string is printed into the PrintStream
+                                        return;
+                                } catch (OutOfMemoryError e) {
+
+                                        // Catch the error and wait for a while
+                                        synchronized(object) {
+                                                try {
+                                                        object.wait(500);
+                                                } catch (InterruptedException ie) {
+
+                                                        // Ignore the exception
+                                                }
+                                        } // synchronized
+                                } // try
+                        } // for j
+                } // for i
+        } // tryToPrintStack()
+
+        /**
+         * Returns recommended size for an array. Default implemetation returns
+         * minimum between <code>size</code> and
+         * {@link #MAX_ARRAY_SIZE MAX_ARRAY_SIZE}.
+         *
+         * @return recommended size for an array.
+         *
+         */
+        public static int getArraySize(long size) {
+                long min = Math.min(MAX_ARRAY_SIZE, size);
+                return (int) min;
+        } // getArraySize()
+} // class Algorithms
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllDiag.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.runner.RunParams;
+
+/**
+ *  Helper that prints information about AllMemoryObjects.
+ */
+public class AllDiag implements Runnable {
+        private long sleepTime;
+
+        public AllDiag() {
+                this(RunParams.getInstance().getSleepTime());
+        }
+
+        public AllDiag(long sleepTime) {
+                this.sleepTime = sleepTime;
+        }
+
+        public void run() {
+                AllMemoryObject.dumpStatistics();
+                // Ensure that interrupt status is not lost
+                if (Thread.currentThread().isInterrupted())
+                        return;
+                try {
+                        Thread.sleep(sleepTime);
+                } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/AllMemoryObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.PrintStream;
+
+/**
+ * An object that occupies approximately given number of bytes in memory
+ * and also records number of allocated instances.
+ */
+public class AllMemoryObject extends MemoryObject {
+        private static int allocatedCount;
+
+        public AllMemoryObject(int size) {
+                super(size);
+                synchronized (AllMemoryObject.class) {
+                        ++allocatedCount;
+                }
+        }
+
+        /**
+         * Returns the number of allocated FinMemoryObjects.
+         */
+        public static int getAllocatedCount() {
+                return allocatedCount;
+        }
+
+        public static void dumpStatistics(PrintStream out) {
+                out.println("Object count: " + getAllocatedCount());
+        }
+
+        public static void dumpStatistics() {
+                dumpStatistics(System.out);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/ArgumentHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.*;
+
+/**
+ * Parser for GC tests' arguments.
+ * <p>
+ * <code>ArgumentHandler</code> handles specific command line arguments
+ * related to way of execution of a test in addition to general arguments
+ * recognized by {@link ArgumentParser <code>ArgumentParser</code>}.
+ * <p>
+ * Following is the list of specific options for <code>ArgumentHandler</code>:
+ * <ul>
+ * <li><code>-iterations="<i>value</i>"</code>, where <i>value</i> must either
+ *     be "infinity", or an integer number, greater than 0. This parameter
+ *     specifies the number of iterations to run the testcase. If the value is
+ *     "infinity", then the test will be run for at least <code>gcTimeout</code>
+ *     minutes. Otherwise, the testcase will be repeated for
+ *     <code>iterations</code> times.
+ * <li><code>-gcTimeout="<i>value</i>"</code>, where <i>value</i> must be an
+ *     integer number, greater than 0. If <i>infinity</i> is set to
+ *     <code>iterations</code>, then the test consider <code>gcTimeout</code>
+ *     argument to run the test for at least specified number of minutes.
+ * <li><code>-threads="<i>value</i>"</code>, where <i>value</i> must be an
+ *     integer number, greater than 0. A user may specify the number of threads
+ *     to start in the test with that paramenter. However, a test may ignore
+ *     this value, if it does know the number of threads to start. It
+ *     depends on a test: read its README file.
+ * <li><code>-memoryEater="<i>value</i>"</code>, where <i>value</i> must be
+ *     either "single", or "multi" string. This argument specifies if a single
+ *     thread should be used to eat the whole heap or not. If "multi" string is
+ *     assigned to <code>-memoryEater</code>, then a number of threads will be
+ *     started to eat the heap. The number is equal to number of available
+ *     processors plus 1.
+ * <li><code>-largeClassesPath="<i>value</i>"</code>, where <i>value</i> is a
+ *     directory to load large classes from.
+ * <li><code>-fieldsLimitation="<i>value</i>"</code>, where <i>value</i> must
+ *     be either "over", or "under" string. This argument specifies what classes
+ *     should be loaded from <code>largeClassesPath</code> directory. If
+ *     <i>over</i> is set, then the classes that have number of fileds over
+ *     JVM limitation should be loaded, otherwise -- classes that have number
+ *     of fileds under limitation.
+ * </ul>
+ * @see ArgumentParser
+ */
+public class ArgumentHandler extends ArgumentParser {
+
+    // Define all possible arguments
+    private final static String ITERATIONS = "iterations";
+    private final static String AGGREGATION_DEPTH = "aggregationDepth";
+    private final static String GC_TIMEOUT = "gcTimeout";
+    private final static String THREADS = "threads";
+    private final static String MEM_EATER = "memoryEater";
+    private final static String LARGE_CLASSES_PATH = "largeClassesPath";
+    private final static String FIELDS_LIMITATION = "fieldsLimitation";
+
+    // An acceptible value for ITERATIONS
+    private final static String INFINITY = "infinity";
+
+    // Acceptible values for MEM_EATER
+    private final static String ME_SINGLE = "single";
+    private final static String ME_MULTI = "multi";
+
+    // Acceptible values for FIELDS_LIMITATION
+    private final static String FL_OVER = "over";
+    private final static String FL_UNDER = "under";
+
+    /**
+     * Keep a copy of raw command-line arguments and parse them;
+     * but throw an exception on parsing error.
+     *
+     * @param args Array of the raw command-line arguments.
+     *
+     * @throws BadOption  If unknown option or illegal option value found
+     *
+     * @see ArgumentParser
+     */
+    public ArgumentHandler(String args[]) {
+        super(args);
+    }
+
+    /**
+     * Returns number of iterations.
+     * <p>
+     * If <code>-iterations="<i>infinity</i>"</code>, the method returns -1.
+     * If the argument is not set, the method returns 1. Otherwise, the
+     * specified number is returned.
+     *
+     * @return number of iterations.
+     *
+     */
+    public int getIterations() {
+        String value = options.getProperty(ITERATIONS, "1");
+
+        if (INFINITY.equals(value))
+            return -1;
+
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not an integer value of \"" + ITERATIONS
+                            + "\" argument: " + value);
+        }
+    }
+
+
+    /**
+     * Returns the depth of object aggregation.
+     * <p>
+     * If the argument is not set, the method returns 0. Otherwise, the
+     * specified number is returned.
+     *
+     * @return number of aggregation depth.
+     *
+     */
+    public int getAggregationDepth() {
+        String value = options.getProperty(AGGREGATION_DEPTH, "0");
+
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not an integer value of \"" + AGGREGATION_DEPTH
+                            + "\" argument: " + value);
+        }
+    }
+
+
+    /**
+     * Returns number of minutes to run the test.
+     * <p>
+     * @return number of minutes to run the test.
+     *
+     */
+    public int getGCTimeout() {
+        String value = options.getProperty(GC_TIMEOUT);
+
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("\"" + GC_TIMEOUT + "\" argument is not defined "
+                            + "or is not integer: " + value);
+        }
+    }
+
+    /**
+     * Returns a directory to load large classes from.
+     * <p>
+     * @return a directory to load large classes from.
+     *
+     */
+    public String getLargeClassesPath() {
+        return options.getProperty(LARGE_CLASSES_PATH);
+    }
+
+    /**
+     * Returns number of threads to start in a test. If <code>threads</code>
+     * is not set, the method returns specified number of threads.
+     * <p>
+     * @param defaultValue default value, if <code>threads</code> is not set.
+     * @return number of threads to start in a test.
+     *
+     */
+    public int getThreads(int defaultValue) {
+        String value = options.getProperty(THREADS);
+
+        if (value == null)
+            return defaultValue;
+
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not an integer value of \"" + THREADS
+                            + "\" argument: " + value);
+        }
+    }
+
+    /**
+     * Returns true if single thread should be used to eat the whole heap,
+     * false otherwise.
+     *
+     * @return true if single thread should be used to eat the whole heap,
+     * false otherwise.
+     *
+     */
+    public boolean isSingleMemoryEater() {
+        String value = options.getProperty(MEM_EATER);
+
+        if (value == null)
+            return true;
+        else if (value.equals(ME_SINGLE))
+            return true;
+        else if (value.equals(ME_MULTI))
+            return false;
+        else
+            throw new TestBug("Value for \"" + MEM_EATER + "\" must be either "
+                            + ME_SINGLE + ", or " + ME_MULTI);
+    }
+
+    /**
+     * Returns true if classes with number of fileds over limitation should be
+     * loaded, false otherwise.
+     *
+     * @return true if classes with number of fileds over limitation should be
+     * loaded, false otherwise.
+     *
+     */
+    public boolean isOverFieldsLimitation() {
+        String value = options.getProperty(FIELDS_LIMITATION);
+
+        if (value == null)
+            return false;
+        else if (value.equals(FL_OVER))
+            return true;
+        else if (value.equals(FL_UNDER))
+            return false;
+        else
+            throw new TestBug("Value for \"" + FIELDS_LIMITATION + "\" must be "
+                            + "either " + FL_OVER + ", or " + FL_UNDER);
+    }
+
+    /**
+     * Checks if an option is allowed and has proper value.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @param option option name
+     * @param value string representation of value
+     *                      (could be an empty string too)
+     *              null if this option has no value
+     * @return <i>true</i> if option is allowed and has proper value,
+     *         <i>false</i> if option is not admissible
+     *
+     * @throws <i>BadOption</i> if option has an illegal value
+     *
+     * @see #parseArguments()
+     */
+    protected boolean checkOption(String option, String value) {
+
+        // Define iterations
+        if (option.equals(ITERATIONS)) {
+            if (INFINITY.equals(value))
+                return true;
+
+            try {
+                int number = Integer.parseInt(value);
+
+                if (number < 1)
+                    throw new BadOption(option + ": value must be greater than "
+                                               + "zero.");
+            } catch (NumberFormatException e) {
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be integer or \"" + INFINITY + "\": "
+                                  + value);
+            }
+            return true;
+        }
+
+        // Define timeout
+        if (option.equals(GC_TIMEOUT)) {
+            try {
+                int number = Integer.parseInt(value);
+
+                if (number < 0)
+                    throw new BadOption(option + ": value must be a positive "
+                                      + "integer");
+            } catch (NumberFormatException e) {
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be integer: " + value);
+            }
+            return true;
+        }
+
+        // Define threads
+        if (option.equals(THREADS)) {
+            try {
+                int number = Integer.parseInt(value);
+
+                if (number < 0)
+                    throw new BadOption(option + ": value must be a positive "
+                                      + "integer");
+            } catch (NumberFormatException e) {
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be integer: " + value);
+            }
+            return true;
+        }
+
+        // Define path to large classes
+        if (option.equals(LARGE_CLASSES_PATH))
+            return true;
+
+        // Define memory eater
+        if (option.equals(MEM_EATER)) {
+            if ( (ME_SINGLE.equals(value)) || (ME_MULTI.equals(value)) )
+                return true;
+            else
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be either " + ME_SINGLE + ", or "
+                                  + ME_MULTI + ": " + value);
+        }
+
+        // Define fields limitation
+        if (option.equals(FIELDS_LIMITATION)) {
+            if ( (FL_OVER.equals(value)) || (FL_UNDER.equals(value)) )
+                return true;
+            else
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be either " + FL_OVER + ", or "
+                                  + FL_UNDER + ": " + value);
+        }
+
+        // Define aggregationDepth
+        if (option.equals(AGGREGATION_DEPTH)) {
+            try {
+                int number = Integer.parseInt(value);
+
+                if (number < 0)
+                    throw new BadOption(option + ": value must be a positive "
+                                      + "integer");
+            } catch (NumberFormatException e) {
+                throw new BadOption("Value for option \"" + option + "\" must "
+                                  + "be integer: " + value);
+            }
+            return true;
+        }
+
+        return super.checkOption(option, value);
+    }
+
+    /**
+     * Checks if the values of all options are consistent.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @throws <i>BadOption</i> if options have inconsistent values
+     *
+     * @see ArgumentParser#parseArguments()
+     */
+    protected void checkOptions() {
+        super.checkOptions();
+    }
+} // ArgumentHandler
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Cell.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.gc.MemoryObject;
+
+public class Cell extends MemoryObject {
+        private int number;
+
+        public Cell(int size, int number) {
+                super(size - 4);
+                setNumber(number);
+        }
+
+        public final int getNumber() {
+                return number;
+        }
+
+        public final void setNumber(int number) {
+                this.number = number;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/CircularLinkedList.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+public class CircularLinkedList {
+        private int objectSize;
+        private LinkedMemoryObject root;
+
+        /**
+         * Create empty circular linked list.
+         *
+         * @param objectSize size of each node in the list
+         */
+        public CircularLinkedList(int objectSize) {
+                this.objectSize = objectSize;
+        }
+
+        /**
+         * Insert new node in the list.
+         */
+        public void grow() {
+                LinkedMemoryObject newnode = new LinkedMemoryObject(objectSize);
+                if (root == null){
+                        root = newnode;
+                        root.setNext(root);
+                        root.setPrev(root);
+                } else {
+                        newnode.setNext(root.getNext());
+                        root.getNext().setPrev(newnode);
+                        root.setNext(newnode);
+                        newnode.setPrev(root);
+                }
+        }
+
+        /**
+         * Get length of the list.
+         *
+         * @return length
+         */
+        public int getLength() {
+                return Memory.getListLength(root);
+        }
+
+        /**
+         * Get length of another list.
+         *
+         * @param list another list
+         * @return length of list
+         */
+        public int getLength(CircularLinkedList list) {
+                return Memory.getListLength(list.root);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/ClassChain.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,5035 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+/**
+ * Object with long dependency chain.
+ *
+ * Instantiation of this class forces loading of all classes Class*.
+ */
+public class ClassChain {
+        public ClassChain(){
+                new Class1();
+        }
+}
+
+class Class1 {
+        public Class1(){
+                new Class2();
+        }
+}
+class Class2 {
+        public Class2(){
+                new Class3();
+        }
+}
+class Class3 {
+        public Class3(){
+                new Class4();
+        }
+}
+class Class4 {
+        public Class4(){
+                new Class5();
+        }
+}
+class Class5 {
+        public Class5(){
+                new Class6();
+        }
+}
+class Class6 {
+        public Class6(){
+                new Class7();
+        }
+}
+class Class7 {
+        public Class7(){
+                new Class8();
+        }
+}
+class Class8 {
+        public Class8(){
+                new Class9();
+        }
+}
+class Class9 {
+        public Class9(){
+                new Class10();
+        }
+}
+class Class10 {
+        public Class10(){
+                new Class11();
+        }
+}
+class Class11 {
+        public Class11(){
+                new Class12();
+        }
+}
+class Class12 {
+        public Class12(){
+                new Class13();
+        }
+}
+class Class13 {
+        public Class13(){
+                new Class14();
+        }
+}
+class Class14 {
+        public Class14(){
+                new Class15();
+        }
+}
+class Class15 {
+        public Class15(){
+                new Class16();
+        }
+}
+class Class16 {
+        public Class16(){
+                new Class17();
+        }
+}
+class Class17 {
+        public Class17(){
+                new Class18();
+        }
+}
+class Class18 {
+        public Class18(){
+                new Class19();
+        }
+}
+class Class19 {
+        public Class19(){
+                new Class20();
+        }
+}
+class Class20 {
+        public Class20(){
+                new Class21();
+        }
+}
+class Class21 {
+        public Class21(){
+                new Class22();
+        }
+}
+class Class22 {
+        public Class22(){
+                new Class23();
+        }
+}
+class Class23 {
+        public Class23(){
+                new Class24();
+        }
+}
+class Class24 {
+        public Class24(){
+                new Class25();
+        }
+}
+class Class25 {
+        public Class25(){
+                new Class26();
+        }
+}
+class Class26 {
+        public Class26(){
+                new Class27();
+        }
+}
+class Class27 {
+        public Class27(){
+                new Class28();
+        }
+}
+class Class28 {
+        public Class28(){
+                new Class29();
+        }
+}
+class Class29 {
+        public Class29(){
+                new Class30();
+        }
+}
+class Class30 {
+        public Class30(){
+                new Class31();
+        }
+}
+class Class31 {
+        public Class31(){
+                new Class32();
+        }
+}
+class Class32 {
+        public Class32(){
+                new Class33();
+        }
+}
+class Class33 {
+        public Class33(){
+                new Class34();
+        }
+}
+class Class34 {
+        public Class34(){
+                new Class35();
+        }
+}
+class Class35 {
+        public Class35(){
+                new Class36();
+        }
+}
+class Class36 {
+        public Class36(){
+                new Class37();
+        }
+}
+class Class37 {
+        public Class37(){
+                new Class38();
+        }
+}
+class Class38 {
+        public Class38(){
+                new Class39();
+        }
+}
+class Class39 {
+        public Class39(){
+                new Class40();
+        }
+}
+class Class40 {
+        public Class40(){
+                new Class41();
+        }
+}
+class Class41 {
+        public Class41(){
+                new Class42();
+        }
+}
+class Class42 {
+        public Class42(){
+                new Class43();
+        }
+}
+class Class43 {
+        public Class43(){
+                new Class44();
+        }
+}
+class Class44 {
+        public Class44(){
+                new Class45();
+        }
+}
+class Class45 {
+        public Class45(){
+                new Class46();
+        }
+}
+class Class46 {
+        public Class46(){
+                new Class47();
+        }
+}
+class Class47 {
+        public Class47(){
+                new Class48();
+        }
+}
+class Class48 {
+        public Class48(){
+                new Class49();
+        }
+}
+class Class49 {
+        public Class49(){
+                new Class50();
+        }
+}
+class Class50 {
+        public Class50(){
+                new Class51();
+        }
+}
+class Class51 {
+        public Class51(){
+                new Class52();
+        }
+}
+class Class52 {
+        public Class52(){
+                new Class53();
+        }
+}
+class Class53 {
+        public Class53(){
+                new Class54();
+        }
+}
+class Class54 {
+        public Class54(){
+                new Class55();
+        }
+}
+class Class55 {
+        public Class55(){
+                new Class56();
+        }
+}
+class Class56 {
+        public Class56(){
+                new Class57();
+        }
+}
+class Class57 {
+        public Class57(){
+                new Class58();
+        }
+}
+class Class58 {
+        public Class58(){
+                new Class59();
+        }
+}
+class Class59 {
+        public Class59(){
+                new Class60();
+        }
+}
+class Class60 {
+        public Class60(){
+                new Class61();
+        }
+}
+class Class61 {
+        public Class61(){
+                new Class62();
+        }
+}
+class Class62 {
+        public Class62(){
+                new Class63();
+        }
+}
+class Class63 {
+        public Class63(){
+                new Class64();
+        }
+}
+class Class64 {
+        public Class64(){
+                new Class65();
+        }
+}
+class Class65 {
+        public Class65(){
+                new Class66();
+        }
+}
+class Class66 {
+        public Class66(){
+                new Class67();
+        }
+}
+class Class67 {
+        public Class67(){
+                new Class68();
+        }
+}
+class Class68 {
+        public Class68(){
+                new Class69();
+        }
+}
+class Class69 {
+        public Class69(){
+                new Class70();
+        }
+}
+class Class70 {
+        public Class70(){
+                new Class71();
+        }
+}
+class Class71 {
+        public Class71(){
+                new Class72();
+        }
+}
+class Class72 {
+        public Class72(){
+                new Class73();
+        }
+}
+class Class73 {
+        public Class73(){
+                new Class74();
+        }
+}
+class Class74 {
+        public Class74(){
+                new Class75();
+        }
+}
+class Class75 {
+        public Class75(){
+                new Class76();
+        }
+}
+class Class76 {
+        public Class76(){
+                new Class77();
+        }
+}
+class Class77 {
+        public Class77(){
+                new Class78();
+        }
+}
+class Class78 {
+        public Class78(){
+                new Class79();
+        }
+}
+class Class79 {
+        public Class79(){
+                new Class80();
+        }
+}
+class Class80 {
+        public Class80(){
+                new Class81();
+        }
+}
+class Class81 {
+        public Class81(){
+                new Class82();
+        }
+}
+class Class82 {
+        public Class82(){
+                new Class83();
+        }
+}
+class Class83 {
+        public Class83(){
+                new Class84();
+        }
+}
+class Class84 {
+        public Class84(){
+                new Class85();
+        }
+}
+class Class85 {
+        public Class85(){
+                new Class86();
+        }
+}
+class Class86 {
+        public Class86(){
+                new Class87();
+        }
+}
+class Class87 {
+        public Class87(){
+                new Class88();
+        }
+}
+class Class88 {
+        public Class88(){
+                new Class89();
+        }
+}
+class Class89 {
+        public Class89(){
+                new Class90();
+        }
+}
+class Class90 {
+        public Class90(){
+                new Class91();
+        }
+}
+class Class91 {
+        public Class91(){
+                new Class92();
+        }
+}
+class Class92 {
+        public Class92(){
+                new Class93();
+        }
+}
+class Class93 {
+        public Class93(){
+                new Class94();
+        }
+}
+class Class94 {
+        public Class94(){
+                new Class95();
+        }
+}
+class Class95 {
+        public Class95(){
+                new Class96();
+        }
+}
+class Class96 {
+        public Class96(){
+                new Class97();
+        }
+}
+class Class97 {
+        public Class97(){
+                new Class98();
+        }
+}
+class Class98 {
+        public Class98(){
+                new Class99();
+        }
+}
+class Class99 {
+        public Class99(){
+                new Class100();
+        }
+}
+class Class100 {
+        public Class100(){
+                new Class101();
+        }
+}
+class Class101 {
+        public Class101(){
+                new Class102();
+        }
+}
+class Class102 {
+        public Class102(){
+                new Class103();
+        }
+}
+class Class103 {
+        public Class103(){
+                new Class104();
+        }
+}
+class Class104 {
+        public Class104(){
+                new Class105();
+        }
+}
+class Class105 {
+        public Class105(){
+                new Class106();
+        }
+}
+class Class106 {
+        public Class106(){
+                new Class107();
+        }
+}
+class Class107 {
+        public Class107(){
+                new Class108();
+        }
+}
+class Class108 {
+        public Class108(){
+                new Class109();
+        }
+}
+class Class109 {
+        public Class109(){
+                new Class110();
+        }
+}
+class Class110 {
+        public Class110(){
+                new Class111();
+        }
+}
+class Class111 {
+        public Class111(){
+                new Class112();
+        }
+}
+class Class112 {
+        public Class112(){
+                new Class113();
+        }
+}
+class Class113 {
+        public Class113(){
+                new Class114();
+        }
+}
+class Class114 {
+        public Class114(){
+                new Class115();
+        }
+}
+class Class115 {
+        public Class115(){
+                new Class116();
+        }
+}
+class Class116 {
+        public Class116(){
+                new Class117();
+        }
+}
+class Class117 {
+        public Class117(){
+                new Class118();
+        }
+}
+class Class118 {
+        public Class118(){
+                new Class119();
+        }
+}
+class Class119 {
+        public Class119(){
+                new Class120();
+        }
+}
+class Class120 {
+        public Class120(){
+                new Class121();
+        }
+}
+class Class121 {
+        public Class121(){
+                new Class122();
+        }
+}
+class Class122 {
+        public Class122(){
+                new Class123();
+        }
+}
+class Class123 {
+        public Class123(){
+                new Class124();
+        }
+}
+class Class124 {
+        public Class124(){
+                new Class125();
+        }
+}
+class Class125 {
+        public Class125(){
+                new Class126();
+        }
+}
+class Class126 {
+        public Class126(){
+                new Class127();
+        }
+}
+class Class127 {
+        public Class127(){
+                new Class128();
+        }
+}
+class Class128 {
+        public Class128(){
+                new Class129();
+        }
+}
+class Class129 {
+        public Class129(){
+                new Class130();
+        }
+}
+class Class130 {
+        public Class130(){
+                new Class131();
+        }
+}
+class Class131 {
+        public Class131(){
+                new Class132();
+        }
+}
+class Class132 {
+        public Class132(){
+                new Class133();
+        }
+}
+class Class133 {
+        public Class133(){
+                new Class134();
+        }
+}
+class Class134 {
+        public Class134(){
+                new Class135();
+        }
+}
+class Class135 {
+        public Class135(){
+                new Class136();
+        }
+}
+class Class136 {
+        public Class136(){
+                new Class137();
+        }
+}
+class Class137 {
+        public Class137(){
+                new Class138();
+        }
+}
+class Class138 {
+        public Class138(){
+                new Class139();
+        }
+}
+class Class139 {
+        public Class139(){
+                new Class140();
+        }
+}
+class Class140 {
+        public Class140(){
+                new Class141();
+        }
+}
+class Class141 {
+        public Class141(){
+                new Class142();
+        }
+}
+class Class142 {
+        public Class142(){
+                new Class143();
+        }
+}
+class Class143 {
+        public Class143(){
+                new Class144();
+        }
+}
+class Class144 {
+        public Class144(){
+                new Class145();
+        }
+}
+class Class145 {
+        public Class145(){
+                new Class146();
+        }
+}
+class Class146 {
+        public Class146(){
+                new Class147();
+        }
+}
+class Class147 {
+        public Class147(){
+                new Class148();
+        }
+}
+class Class148 {
+        public Class148(){
+                new Class149();
+        }
+}
+class Class149 {
+        public Class149(){
+                new Class150();
+        }
+}
+class Class150 {
+        public Class150(){
+                new Class151();
+        }
+}
+class Class151 {
+        public Class151(){
+                new Class152();
+        }
+}
+class Class152 {
+        public Class152(){
+                new Class153();
+        }
+}
+class Class153 {
+        public Class153(){
+                new Class154();
+        }
+}
+class Class154 {
+        public Class154(){
+                new Class155();
+        }
+}
+class Class155 {
+        public Class155(){
+                new Class156();
+        }
+}
+class Class156 {
+        public Class156(){
+                new Class157();
+        }
+}
+class Class157 {
+        public Class157(){
+                new Class158();
+        }
+}
+class Class158 {
+        public Class158(){
+                new Class159();
+        }
+}
+class Class159 {
+        public Class159(){
+                new Class160();
+        }
+}
+class Class160 {
+        public Class160(){
+                new Class161();
+        }
+}
+class Class161 {
+        public Class161(){
+                new Class162();
+        }
+}
+class Class162 {
+        public Class162(){
+                new Class163();
+        }
+}
+class Class163 {
+        public Class163(){
+                new Class164();
+        }
+}
+class Class164 {
+        public Class164(){
+                new Class165();
+        }
+}
+class Class165 {
+        public Class165(){
+                new Class166();
+        }
+}
+class Class166 {
+        public Class166(){
+                new Class167();
+        }
+}
+class Class167 {
+        public Class167(){
+                new Class168();
+        }
+}
+class Class168 {
+        public Class168(){
+                new Class169();
+        }
+}
+class Class169 {
+        public Class169(){
+                new Class170();
+        }
+}
+class Class170 {
+        public Class170(){
+                new Class171();
+        }
+}
+class Class171 {
+        public Class171(){
+                new Class172();
+        }
+}
+class Class172 {
+        public Class172(){
+                new Class173();
+        }
+}
+class Class173 {
+        public Class173(){
+                new Class174();
+        }
+}
+class Class174 {
+        public Class174(){
+                new Class175();
+        }
+}
+class Class175 {
+        public Class175(){
+                new Class176();
+        }
+}
+class Class176 {
+        public Class176(){
+                new Class177();
+        }
+}
+class Class177 {
+        public Class177(){
+                new Class178();
+        }
+}
+class Class178 {
+        public Class178(){
+                new Class179();
+        }
+}
+class Class179 {
+        public Class179(){
+                new Class180();
+        }
+}
+class Class180 {
+        public Class180(){
+                new Class181();
+        }
+}
+class Class181 {
+        public Class181(){
+                new Class182();
+        }
+}
+class Class182 {
+        public Class182(){
+                new Class183();
+        }
+}
+class Class183 {
+        public Class183(){
+                new Class184();
+        }
+}
+class Class184 {
+        public Class184(){
+                new Class185();
+        }
+}
+class Class185 {
+        public Class185(){
+                new Class186();
+        }
+}
+class Class186 {
+        public Class186(){
+                new Class187();
+        }
+}
+class Class187 {
+        public Class187(){
+                new Class188();
+        }
+}
+class Class188 {
+        public Class188(){
+                new Class189();
+        }
+}
+class Class189 {
+        public Class189(){
+                new Class190();
+        }
+}
+class Class190 {
+        public Class190(){
+                new Class191();
+        }
+}
+class Class191 {
+        public Class191(){
+                new Class192();
+        }
+}
+class Class192 {
+        public Class192(){
+                new Class193();
+        }
+}
+class Class193 {
+        public Class193(){
+                new Class194();
+        }
+}
+class Class194 {
+        public Class194(){
+                new Class195();
+        }
+}
+class Class195 {
+        public Class195(){
+                new Class196();
+        }
+}
+class Class196 {
+        public Class196(){
+                new Class197();
+        }
+}
+class Class197 {
+        public Class197(){
+                new Class198();
+        }
+}
+class Class198 {
+        public Class198(){
+                new Class199();
+        }
+}
+class Class199 {
+        public Class199(){
+                new Class200();
+        }
+}
+class Class200 {
+        public Class200(){
+                new Class201();
+        }
+}
+class Class201 {
+        public Class201(){
+                new Class202();
+        }
+}
+class Class202 {
+        public Class202(){
+                new Class203();
+        }
+}
+class Class203 {
+        public Class203(){
+                new Class204();
+        }
+}
+class Class204 {
+        public Class204(){
+                new Class205();
+        }
+}
+class Class205 {
+        public Class205(){
+                new Class206();
+        }
+}
+class Class206 {
+        public Class206(){
+                new Class207();
+        }
+}
+class Class207 {
+        public Class207(){
+                new Class208();
+        }
+}
+class Class208 {
+        public Class208(){
+                new Class209();
+        }
+}
+class Class209 {
+        public Class209(){
+                new Class210();
+        }
+}
+class Class210 {
+        public Class210(){
+                new Class211();
+        }
+}
+class Class211 {
+        public Class211(){
+                new Class212();
+        }
+}
+class Class212 {
+        public Class212(){
+                new Class213();
+        }
+}
+class Class213 {
+        public Class213(){
+                new Class214();
+        }
+}
+class Class214 {
+        public Class214(){
+                new Class215();
+        }
+}
+class Class215 {
+        public Class215(){
+                new Class216();
+        }
+}
+class Class216 {
+        public Class216(){
+                new Class217();
+        }
+}
+class Class217 {
+        public Class217(){
+                new Class218();
+        }
+}
+class Class218 {
+        public Class218(){
+                new Class219();
+        }
+}
+class Class219 {
+        public Class219(){
+                new Class220();
+        }
+}
+class Class220 {
+        public Class220(){
+                new Class221();
+        }
+}
+class Class221 {
+        public Class221(){
+                new Class222();
+        }
+}
+class Class222 {
+        public Class222(){
+                new Class223();
+        }
+}
+class Class223 {
+        public Class223(){
+                new Class224();
+        }
+}
+class Class224 {
+        public Class224(){
+                new Class225();
+        }
+}
+class Class225 {
+        public Class225(){
+                new Class226();
+        }
+}
+class Class226 {
+        public Class226(){
+                new Class227();
+        }
+}
+class Class227 {
+        public Class227(){
+                new Class228();
+        }
+}
+class Class228 {
+        public Class228(){
+                new Class229();
+        }
+}
+class Class229 {
+        public Class229(){
+                new Class230();
+        }
+}
+class Class230 {
+        public Class230(){
+                new Class231();
+        }
+}
+class Class231 {
+        public Class231(){
+                new Class232();
+        }
+}
+class Class232 {
+        public Class232(){
+                new Class233();
+        }
+}
+class Class233 {
+        public Class233(){
+                new Class234();
+        }
+}
+class Class234 {
+        public Class234(){
+                new Class235();
+        }
+}
+class Class235 {
+        public Class235(){
+                new Class236();
+        }
+}
+class Class236 {
+        public Class236(){
+                new Class237();
+        }
+}
+class Class237 {
+        public Class237(){
+                new Class238();
+        }
+}
+class Class238 {
+        public Class238(){
+                new Class239();
+        }
+}
+class Class239 {
+        public Class239(){
+                new Class240();
+        }
+}
+class Class240 {
+        public Class240(){
+                new Class241();
+        }
+}
+class Class241 {
+        public Class241(){
+                new Class242();
+        }
+}
+class Class242 {
+        public Class242(){
+                new Class243();
+        }
+}
+class Class243 {
+        public Class243(){
+                new Class244();
+        }
+}
+class Class244 {
+        public Class244(){
+                new Class245();
+        }
+}
+class Class245 {
+        public Class245(){
+                new Class246();
+        }
+}
+class Class246 {
+        public Class246(){
+                new Class247();
+        }
+}
+class Class247 {
+        public Class247(){
+                new Class248();
+        }
+}
+class Class248 {
+        public Class248(){
+                new Class249();
+        }
+}
+class Class249 {
+        public Class249(){
+                new Class250();
+        }
+}
+class Class250 {
+        public Class250(){
+                new Class251();
+        }
+}
+class Class251 {
+        public Class251(){
+                new Class252();
+        }
+}
+class Class252 {
+        public Class252(){
+                new Class253();
+        }
+}
+class Class253 {
+        public Class253(){
+                new Class254();
+        }
+}
+class Class254 {
+        public Class254(){
+                new Class255();
+        }
+}
+class Class255 {
+        public Class255(){
+                new Class256();
+        }
+}
+class Class256 {
+        public Class256(){
+                new Class257();
+        }
+}
+class Class257 {
+        public Class257(){
+                new Class258();
+        }
+}
+class Class258 {
+        public Class258(){
+                new Class259();
+        }
+}
+class Class259 {
+        public Class259(){
+                new Class260();
+        }
+}
+class Class260 {
+        public Class260(){
+                new Class261();
+        }
+}
+class Class261 {
+        public Class261(){
+                new Class262();
+        }
+}
+class Class262 {
+        public Class262(){
+                new Class263();
+        }
+}
+class Class263 {
+        public Class263(){
+                new Class264();
+        }
+}
+class Class264 {
+        public Class264(){
+                new Class265();
+        }
+}
+class Class265 {
+        public Class265(){
+                new Class266();
+        }
+}
+class Class266 {
+        public Class266(){
+                new Class267();
+        }
+}
+class Class267 {
+        public Class267(){
+                new Class268();
+        }
+}
+class Class268 {
+        public Class268(){
+                new Class269();
+        }
+}
+class Class269 {
+        public Class269(){
+                new Class270();
+        }
+}
+class Class270 {
+        public Class270(){
+                new Class271();
+        }
+}
+class Class271 {
+        public Class271(){
+                new Class272();
+        }
+}
+class Class272 {
+        public Class272(){
+                new Class273();
+        }
+}
+class Class273 {
+        public Class273(){
+                new Class274();
+        }
+}
+class Class274 {
+        public Class274(){
+                new Class275();
+        }
+}
+class Class275 {
+        public Class275(){
+                new Class276();
+        }
+}
+class Class276 {
+        public Class276(){
+                new Class277();
+        }
+}
+class Class277 {
+        public Class277(){
+                new Class278();
+        }
+}
+class Class278 {
+        public Class278(){
+                new Class279();
+        }
+}
+class Class279 {
+        public Class279(){
+                new Class280();
+        }
+}
+class Class280 {
+        public Class280(){
+                new Class281();
+        }
+}
+class Class281 {
+        public Class281(){
+                new Class282();
+        }
+}
+class Class282 {
+        public Class282(){
+                new Class283();
+        }
+}
+class Class283 {
+        public Class283(){
+                new Class284();
+        }
+}
+class Class284 {
+        public Class284(){
+                new Class285();
+        }
+}
+class Class285 {
+        public Class285(){
+                new Class286();
+        }
+}
+class Class286 {
+        public Class286(){
+                new Class287();
+        }
+}
+class Class287 {
+        public Class287(){
+                new Class288();
+        }
+}
+class Class288 {
+        public Class288(){
+                new Class289();
+        }
+}
+class Class289 {
+        public Class289(){
+                new Class290();
+        }
+}
+class Class290 {
+        public Class290(){
+                new Class291();
+        }
+}
+class Class291 {
+        public Class291(){
+                new Class292();
+        }
+}
+class Class292 {
+        public Class292(){
+                new Class293();
+        }
+}
+class Class293 {
+        public Class293(){
+                new Class294();
+        }
+}
+class Class294 {
+        public Class294(){
+                new Class295();
+        }
+}
+class Class295 {
+        public Class295(){
+                new Class296();
+        }
+}
+class Class296 {
+        public Class296(){
+                new Class297();
+        }
+}
+class Class297 {
+        public Class297(){
+                new Class298();
+        }
+}
+class Class298 {
+        public Class298(){
+                new Class299();
+        }
+}
+class Class299 {
+        public Class299(){
+                new Class300();
+        }
+}
+class Class300 {
+        public Class300(){
+                new Class301();
+        }
+}
+class Class301 {
+        public Class301(){
+                new Class302();
+        }
+}
+class Class302 {
+        public Class302(){
+                new Class303();
+        }
+}
+class Class303 {
+        public Class303(){
+                new Class304();
+        }
+}
+class Class304 {
+        public Class304(){
+                new Class305();
+        }
+}
+class Class305 {
+        public Class305(){
+                new Class306();
+        }
+}
+class Class306 {
+        public Class306(){
+                new Class307();
+        }
+}
+class Class307 {
+        public Class307(){
+                new Class308();
+        }
+}
+class Class308 {
+        public Class308(){
+                new Class309();
+        }
+}
+class Class309 {
+        public Class309(){
+                new Class310();
+        }
+}
+class Class310 {
+        public Class310(){
+                new Class311();
+        }
+}
+class Class311 {
+        public Class311(){
+                new Class312();
+        }
+}
+class Class312 {
+        public Class312(){
+                new Class313();
+        }
+}
+class Class313 {
+        public Class313(){
+                new Class314();
+        }
+}
+class Class314 {
+        public Class314(){
+                new Class315();
+        }
+}
+class Class315 {
+        public Class315(){
+                new Class316();
+        }
+}
+class Class316 {
+        public Class316(){
+                new Class317();
+        }
+}
+class Class317 {
+        public Class317(){
+                new Class318();
+        }
+}
+class Class318 {
+        public Class318(){
+                new Class319();
+        }
+}
+class Class319 {
+        public Class319(){
+                new Class320();
+        }
+}
+class Class320 {
+        public Class320(){
+                new Class321();
+        }
+}
+class Class321 {
+        public Class321(){
+                new Class322();
+        }
+}
+class Class322 {
+        public Class322(){
+                new Class323();
+        }
+}
+class Class323 {
+        public Class323(){
+                new Class324();
+        }
+}
+class Class324 {
+        public Class324(){
+                new Class325();
+        }
+}
+class Class325 {
+        public Class325(){
+                new Class326();
+        }
+}
+class Class326 {
+        public Class326(){
+                new Class327();
+        }
+}
+class Class327 {
+        public Class327(){
+                new Class328();
+        }
+}
+class Class328 {
+        public Class328(){
+                new Class329();
+        }
+}
+class Class329 {
+        public Class329(){
+                new Class330();
+        }
+}
+class Class330 {
+        public Class330(){
+                new Class331();
+        }
+}
+class Class331 {
+        public Class331(){
+                new Class332();
+        }
+}
+class Class332 {
+        public Class332(){
+                new Class333();
+        }
+}
+class Class333 {
+        public Class333(){
+                new Class334();
+        }
+}
+class Class334 {
+        public Class334(){
+                new Class335();
+        }
+}
+class Class335 {
+        public Class335(){
+                new Class336();
+        }
+}
+class Class336 {
+        public Class336(){
+                new Class337();
+        }
+}
+class Class337 {
+        public Class337(){
+                new Class338();
+        }
+}
+class Class338 {
+        public Class338(){
+                new Class339();
+        }
+}
+class Class339 {
+        public Class339(){
+                new Class340();
+        }
+}
+class Class340 {
+        public Class340(){
+                new Class341();
+        }
+}
+class Class341 {
+        public Class341(){
+                new Class342();
+        }
+}
+class Class342 {
+        public Class342(){
+                new Class343();
+        }
+}
+class Class343 {
+        public Class343(){
+                new Class344();
+        }
+}
+class Class344 {
+        public Class344(){
+                new Class345();
+        }
+}
+class Class345 {
+        public Class345(){
+                new Class346();
+        }
+}
+class Class346 {
+        public Class346(){
+                new Class347();
+        }
+}
+class Class347 {
+        public Class347(){
+                new Class348();
+        }
+}
+class Class348 {
+        public Class348(){
+                new Class349();
+        }
+}
+class Class349 {
+        public Class349(){
+                new Class350();
+        }
+}
+class Class350 {
+        public Class350(){
+                new Class351();
+        }
+}
+class Class351 {
+        public Class351(){
+                new Class352();
+        }
+}
+class Class352 {
+        public Class352(){
+                new Class353();
+        }
+}
+class Class353 {
+        public Class353(){
+                new Class354();
+        }
+}
+class Class354 {
+        public Class354(){
+                new Class355();
+        }
+}
+class Class355 {
+        public Class355(){
+                new Class356();
+        }
+}
+class Class356 {
+        public Class356(){
+                new Class357();
+        }
+}
+class Class357 {
+        public Class357(){
+                new Class358();
+        }
+}
+class Class358 {
+        public Class358(){
+                new Class359();
+        }
+}
+class Class359 {
+        public Class359(){
+                new Class360();
+        }
+}
+class Class360 {
+        public Class360(){
+                new Class361();
+        }
+}
+class Class361 {
+        public Class361(){
+                new Class362();
+        }
+}
+class Class362 {
+        public Class362(){
+                new Class363();
+        }
+}
+class Class363 {
+        public Class363(){
+                new Class364();
+        }
+}
+class Class364 {
+        public Class364(){
+                new Class365();
+        }
+}
+class Class365 {
+        public Class365(){
+                new Class366();
+        }
+}
+class Class366 {
+        public Class366(){
+                new Class367();
+        }
+}
+class Class367 {
+        public Class367(){
+                new Class368();
+        }
+}
+class Class368 {
+        public Class368(){
+                new Class369();
+        }
+}
+class Class369 {
+        public Class369(){
+                new Class370();
+        }
+}
+class Class370 {
+        public Class370(){
+                new Class371();
+        }
+}
+class Class371 {
+        public Class371(){
+                new Class372();
+        }
+}
+class Class372 {
+        public Class372(){
+                new Class373();
+        }
+}
+class Class373 {
+        public Class373(){
+                new Class374();
+        }
+}
+class Class374 {
+        public Class374(){
+                new Class375();
+        }
+}
+class Class375 {
+        public Class375(){
+                new Class376();
+        }
+}
+class Class376 {
+        public Class376(){
+                new Class377();
+        }
+}
+class Class377 {
+        public Class377(){
+                new Class378();
+        }
+}
+class Class378 {
+        public Class378(){
+                new Class379();
+        }
+}
+class Class379 {
+        public Class379(){
+                new Class380();
+        }
+}
+class Class380 {
+        public Class380(){
+                new Class381();
+        }
+}
+class Class381 {
+        public Class381(){
+                new Class382();
+        }
+}
+class Class382 {
+        public Class382(){
+                new Class383();
+        }
+}
+class Class383 {
+        public Class383(){
+                new Class384();
+        }
+}
+class Class384 {
+        public Class384(){
+                new Class385();
+        }
+}
+class Class385 {
+        public Class385(){
+                new Class386();
+        }
+}
+class Class386 {
+        public Class386(){
+                new Class387();
+        }
+}
+class Class387 {
+        public Class387(){
+                new Class388();
+        }
+}
+class Class388 {
+        public Class388(){
+                new Class389();
+        }
+}
+class Class389 {
+        public Class389(){
+                new Class390();
+        }
+}
+class Class390 {
+        public Class390(){
+                new Class391();
+        }
+}
+class Class391 {
+        public Class391(){
+                new Class392();
+        }
+}
+class Class392 {
+        public Class392(){
+                new Class393();
+        }
+}
+class Class393 {
+        public Class393(){
+                new Class394();
+        }
+}
+class Class394 {
+        public Class394(){
+                new Class395();
+        }
+}
+class Class395 {
+        public Class395(){
+                new Class396();
+        }
+}
+class Class396 {
+        public Class396(){
+                new Class397();
+        }
+}
+class Class397 {
+        public Class397(){
+                new Class398();
+        }
+}
+class Class398 {
+        public Class398(){
+                new Class399();
+        }
+}
+class Class399 {
+        public Class399(){
+                new Class400();
+        }
+}
+class Class400 {
+        public Class400(){
+                new Class401();
+        }
+}
+class Class401 {
+        public Class401(){
+                new Class402();
+        }
+}
+class Class402 {
+        public Class402(){
+                new Class403();
+        }
+}
+class Class403 {
+        public Class403(){
+                new Class404();
+        }
+}
+class Class404 {
+        public Class404(){
+                new Class405();
+        }
+}
+class Class405 {
+        public Class405(){
+                new Class406();
+        }
+}
+class Class406 {
+        public Class406(){
+                new Class407();
+        }
+}
+class Class407 {
+        public Class407(){
+                new Class408();
+        }
+}
+class Class408 {
+        public Class408(){
+                new Class409();
+        }
+}
+class Class409 {
+        public Class409(){
+                new Class410();
+        }
+}
+class Class410 {
+        public Class410(){
+                new Class411();
+        }
+}
+class Class411 {
+        public Class411(){
+                new Class412();
+        }
+}
+class Class412 {
+        public Class412(){
+                new Class413();
+        }
+}
+class Class413 {
+        public Class413(){
+                new Class414();
+        }
+}
+class Class414 {
+        public Class414(){
+                new Class415();
+        }
+}
+class Class415 {
+        public Class415(){
+                new Class416();
+        }
+}
+class Class416 {
+        public Class416(){
+                new Class417();
+        }
+}
+class Class417 {
+        public Class417(){
+                new Class418();
+        }
+}
+class Class418 {
+        public Class418(){
+                new Class419();
+        }
+}
+class Class419 {
+        public Class419(){
+                new Class420();
+        }
+}
+class Class420 {
+        public Class420(){
+                new Class421();
+        }
+}
+class Class421 {
+        public Class421(){
+                new Class422();
+        }
+}
+class Class422 {
+        public Class422(){
+                new Class423();
+        }
+}
+class Class423 {
+        public Class423(){
+                new Class424();
+        }
+}
+class Class424 {
+        public Class424(){
+                new Class425();
+        }
+}
+class Class425 {
+        public Class425(){
+                new Class426();
+        }
+}
+class Class426 {
+        public Class426(){
+                new Class427();
+        }
+}
+class Class427 {
+        public Class427(){
+                new Class428();
+        }
+}
+class Class428 {
+        public Class428(){
+                new Class429();
+        }
+}
+class Class429 {
+        public Class429(){
+                new Class430();
+        }
+}
+class Class430 {
+        public Class430(){
+                new Class431();
+        }
+}
+class Class431 {
+        public Class431(){
+                new Class432();
+        }
+}
+class Class432 {
+        public Class432(){
+                new Class433();
+        }
+}
+class Class433 {
+        public Class433(){
+                new Class434();
+        }
+}
+class Class434 {
+        public Class434(){
+                new Class435();
+        }
+}
+class Class435 {
+        public Class435(){
+                new Class436();
+        }
+}
+class Class436 {
+        public Class436(){
+                new Class437();
+        }
+}
+class Class437 {
+        public Class437(){
+                new Class438();
+        }
+}
+class Class438 {
+        public Class438(){
+                new Class439();
+        }
+}
+class Class439 {
+        public Class439(){
+                new Class440();
+        }
+}
+class Class440 {
+        public Class440(){
+                new Class441();
+        }
+}
+class Class441 {
+        public Class441(){
+                new Class442();
+        }
+}
+class Class442 {
+        public Class442(){
+                new Class443();
+        }
+}
+class Class443 {
+        public Class443(){
+                new Class444();
+        }
+}
+class Class444 {
+        public Class444(){
+                new Class445();
+        }
+}
+class Class445 {
+        public Class445(){
+                new Class446();
+        }
+}
+class Class446 {
+        public Class446(){
+                new Class447();
+        }
+}
+class Class447 {
+        public Class447(){
+                new Class448();
+        }
+}
+class Class448 {
+        public Class448(){
+                new Class449();
+        }
+}
+class Class449 {
+        public Class449(){
+                new Class450();
+        }
+}
+class Class450 {
+        public Class450(){
+                new Class451();
+        }
+}
+class Class451 {
+        public Class451(){
+                new Class452();
+        }
+}
+class Class452 {
+        public Class452(){
+                new Class453();
+        }
+}
+class Class453 {
+        public Class453(){
+                new Class454();
+        }
+}
+class Class454 {
+        public Class454(){
+                new Class455();
+        }
+}
+class Class455 {
+        public Class455(){
+                new Class456();
+        }
+}
+class Class456 {
+        public Class456(){
+                new Class457();
+        }
+}
+class Class457 {
+        public Class457(){
+                new Class458();
+        }
+}
+class Class458 {
+        public Class458(){
+                new Class459();
+        }
+}
+class Class459 {
+        public Class459(){
+                new Class460();
+        }
+}
+class Class460 {
+        public Class460(){
+                new Class461();
+        }
+}
+class Class461 {
+        public Class461(){
+                new Class462();
+        }
+}
+class Class462 {
+        public Class462(){
+                new Class463();
+        }
+}
+class Class463 {
+        public Class463(){
+                new Class464();
+        }
+}
+class Class464 {
+        public Class464(){
+                new Class465();
+        }
+}
+class Class465 {
+        public Class465(){
+                new Class466();
+        }
+}
+class Class466 {
+        public Class466(){
+                new Class467();
+        }
+}
+class Class467 {
+        public Class467(){
+                new Class468();
+        }
+}
+class Class468 {
+        public Class468(){
+                new Class469();
+        }
+}
+class Class469 {
+        public Class469(){
+                new Class470();
+        }
+}
+class Class470 {
+        public Class470(){
+                new Class471();
+        }
+}
+class Class471 {
+        public Class471(){
+                new Class472();
+        }
+}
+class Class472 {
+        public Class472(){
+                new Class473();
+        }
+}
+class Class473 {
+        public Class473(){
+                new Class474();
+        }
+}
+class Class474 {
+        public Class474(){
+                new Class475();
+        }
+}
+class Class475 {
+        public Class475(){
+                new Class476();
+        }
+}
+class Class476 {
+        public Class476(){
+                new Class477();
+        }
+}
+class Class477 {
+        public Class477(){
+                new Class478();
+        }
+}
+class Class478 {
+        public Class478(){
+                new Class479();
+        }
+}
+class Class479 {
+        public Class479(){
+                new Class480();
+        }
+}
+class Class480 {
+        public Class480(){
+                new Class481();
+        }
+}
+class Class481 {
+        public Class481(){
+                new Class482();
+        }
+}
+class Class482 {
+        public Class482(){
+                new Class483();
+        }
+}
+class Class483 {
+        public Class483(){
+                new Class484();
+        }
+}
+class Class484 {
+        public Class484(){
+                new Class485();
+        }
+}
+class Class485 {
+        public Class485(){
+                new Class486();
+        }
+}
+class Class486 {
+        public Class486(){
+                new Class487();
+        }
+}
+class Class487 {
+        public Class487(){
+                new Class488();
+        }
+}
+class Class488 {
+        public Class488(){
+                new Class489();
+        }
+}
+class Class489 {
+        public Class489(){
+                new Class490();
+        }
+}
+class Class490 {
+        public Class490(){
+                new Class491();
+        }
+}
+class Class491 {
+        public Class491(){
+                new Class492();
+        }
+}
+class Class492 {
+        public Class492(){
+                new Class493();
+        }
+}
+class Class493 {
+        public Class493(){
+                new Class494();
+        }
+}
+class Class494 {
+        public Class494(){
+                new Class495();
+        }
+}
+class Class495 {
+        public Class495(){
+                new Class496();
+        }
+}
+class Class496 {
+        public Class496(){
+                new Class497();
+        }
+}
+class Class497 {
+        public Class497(){
+                new Class498();
+        }
+}
+class Class498 {
+        public Class498(){
+                new Class499();
+        }
+}
+class Class499 {
+        public Class499(){
+                new Class500();
+        }
+}
+class Class500 {
+        public Class500(){
+                new Class501();
+        }
+}
+class Class501 {
+        public Class501(){
+                new Class502();
+        }
+}
+class Class502 {
+        public Class502(){
+                new Class503();
+        }
+}
+class Class503 {
+        public Class503(){
+                new Class504();
+        }
+}
+class Class504 {
+        public Class504(){
+                new Class505();
+        }
+}
+class Class505 {
+        public Class505(){
+                new Class506();
+        }
+}
+class Class506 {
+        public Class506(){
+                new Class507();
+        }
+}
+class Class507 {
+        public Class507(){
+                new Class508();
+        }
+}
+class Class508 {
+        public Class508(){
+                new Class509();
+        }
+}
+class Class509 {
+        public Class509(){
+                new Class510();
+        }
+}
+class Class510 {
+        public Class510(){
+                new Class511();
+        }
+}
+class Class511 {
+        public Class511(){
+                new Class512();
+        }
+}
+class Class512 {
+        public Class512(){
+                new Class513();
+        }
+}
+class Class513 {
+        public Class513(){
+                new Class514();
+        }
+}
+class Class514 {
+        public Class514(){
+                new Class515();
+        }
+}
+class Class515 {
+        public Class515(){
+                new Class516();
+        }
+}
+class Class516 {
+        public Class516(){
+                new Class517();
+        }
+}
+class Class517 {
+        public Class517(){
+                new Class518();
+        }
+}
+class Class518 {
+        public Class518(){
+                new Class519();
+        }
+}
+class Class519 {
+        public Class519(){
+                new Class520();
+        }
+}
+class Class520 {
+        public Class520(){
+                new Class521();
+        }
+}
+class Class521 {
+        public Class521(){
+                new Class522();
+        }
+}
+class Class522 {
+        public Class522(){
+                new Class523();
+        }
+}
+class Class523 {
+        public Class523(){
+                new Class524();
+        }
+}
+class Class524 {
+        public Class524(){
+                new Class525();
+        }
+}
+class Class525 {
+        public Class525(){
+                new Class526();
+        }
+}
+class Class526 {
+        public Class526(){
+                new Class527();
+        }
+}
+class Class527 {
+        public Class527(){
+                new Class528();
+        }
+}
+class Class528 {
+        public Class528(){
+                new Class529();
+        }
+}
+class Class529 {
+        public Class529(){
+                new Class530();
+        }
+}
+class Class530 {
+        public Class530(){
+                new Class531();
+        }
+}
+class Class531 {
+        public Class531(){
+                new Class532();
+        }
+}
+class Class532 {
+        public Class532(){
+                new Class533();
+        }
+}
+class Class533 {
+        public Class533(){
+                new Class534();
+        }
+}
+class Class534 {
+        public Class534(){
+                new Class535();
+        }
+}
+class Class535 {
+        public Class535(){
+                new Class536();
+        }
+}
+class Class536 {
+        public Class536(){
+                new Class537();
+        }
+}
+class Class537 {
+        public Class537(){
+                new Class538();
+        }
+}
+class Class538 {
+        public Class538(){
+                new Class539();
+        }
+}
+class Class539 {
+        public Class539(){
+                new Class540();
+        }
+}
+class Class540 {
+        public Class540(){
+                new Class541();
+        }
+}
+class Class541 {
+        public Class541(){
+                new Class542();
+        }
+}
+class Class542 {
+        public Class542(){
+                new Class543();
+        }
+}
+class Class543 {
+        public Class543(){
+                new Class544();
+        }
+}
+class Class544 {
+        public Class544(){
+                new Class545();
+        }
+}
+class Class545 {
+        public Class545(){
+                new Class546();
+        }
+}
+class Class546 {
+        public Class546(){
+                new Class547();
+        }
+}
+class Class547 {
+        public Class547(){
+                new Class548();
+        }
+}
+class Class548 {
+        public Class548(){
+                new Class549();
+        }
+}
+class Class549 {
+        public Class549(){
+                new Class550();
+        }
+}
+class Class550 {
+        public Class550(){
+                new Class551();
+        }
+}
+class Class551 {
+        public Class551(){
+                new Class552();
+        }
+}
+class Class552 {
+        public Class552(){
+                new Class553();
+        }
+}
+class Class553 {
+        public Class553(){
+                new Class554();
+        }
+}
+class Class554 {
+        public Class554(){
+                new Class555();
+        }
+}
+class Class555 {
+        public Class555(){
+                new Class556();
+        }
+}
+class Class556 {
+        public Class556(){
+                new Class557();
+        }
+}
+class Class557 {
+        public Class557(){
+                new Class558();
+        }
+}
+class Class558 {
+        public Class558(){
+                new Class559();
+        }
+}
+class Class559 {
+        public Class559(){
+                new Class560();
+        }
+}
+class Class560 {
+        public Class560(){
+                new Class561();
+        }
+}
+class Class561 {
+        public Class561(){
+                new Class562();
+        }
+}
+class Class562 {
+        public Class562(){
+                new Class563();
+        }
+}
+class Class563 {
+        public Class563(){
+                new Class564();
+        }
+}
+class Class564 {
+        public Class564(){
+                new Class565();
+        }
+}
+class Class565 {
+        public Class565(){
+                new Class566();
+        }
+}
+class Class566 {
+        public Class566(){
+                new Class567();
+        }
+}
+class Class567 {
+        public Class567(){
+                new Class568();
+        }
+}
+class Class568 {
+        public Class568(){
+                new Class569();
+        }
+}
+class Class569 {
+        public Class569(){
+                new Class570();
+        }
+}
+class Class570 {
+        public Class570(){
+                new Class571();
+        }
+}
+class Class571 {
+        public Class571(){
+                new Class572();
+        }
+}
+class Class572 {
+        public Class572(){
+                new Class573();
+        }
+}
+class Class573 {
+        public Class573(){
+                new Class574();
+        }
+}
+class Class574 {
+        public Class574(){
+                new Class575();
+        }
+}
+class Class575 {
+        public Class575(){
+                new Class576();
+        }
+}
+class Class576 {
+        public Class576(){
+                new Class577();
+        }
+}
+class Class577 {
+        public Class577(){
+                new Class578();
+        }
+}
+class Class578 {
+        public Class578(){
+                new Class579();
+        }
+}
+class Class579 {
+        public Class579(){
+                new Class580();
+        }
+}
+class Class580 {
+        public Class580(){
+                new Class581();
+        }
+}
+class Class581 {
+        public Class581(){
+                new Class582();
+        }
+}
+class Class582 {
+        public Class582(){
+                new Class583();
+        }
+}
+class Class583 {
+        public Class583(){
+                new Class584();
+        }
+}
+class Class584 {
+        public Class584(){
+                new Class585();
+        }
+}
+class Class585 {
+        public Class585(){
+                new Class586();
+        }
+}
+class Class586 {
+        public Class586(){
+                new Class587();
+        }
+}
+class Class587 {
+        public Class587(){
+                new Class588();
+        }
+}
+class Class588 {
+        public Class588(){
+                new Class589();
+        }
+}
+class Class589 {
+        public Class589(){
+                new Class590();
+        }
+}
+class Class590 {
+        public Class590(){
+                new Class591();
+        }
+}
+class Class591 {
+        public Class591(){
+                new Class592();
+        }
+}
+class Class592 {
+        public Class592(){
+                new Class593();
+        }
+}
+class Class593 {
+        public Class593(){
+                new Class594();
+        }
+}
+class Class594 {
+        public Class594(){
+                new Class595();
+        }
+}
+class Class595 {
+        public Class595(){
+                new Class596();
+        }
+}
+class Class596 {
+        public Class596(){
+                new Class597();
+        }
+}
+class Class597 {
+        public Class597(){
+                new Class598();
+        }
+}
+class Class598 {
+        public Class598(){
+                new Class599();
+        }
+}
+class Class599 {
+        public Class599(){
+                new Class600();
+        }
+}
+class Class600 {
+        public Class600(){
+                new Class601();
+        }
+}
+class Class601 {
+        public Class601(){
+                new Class602();
+        }
+}
+class Class602 {
+        public Class602(){
+                new Class603();
+        }
+}
+class Class603 {
+        public Class603(){
+                new Class604();
+        }
+}
+class Class604 {
+        public Class604(){
+                new Class605();
+        }
+}
+class Class605 {
+        public Class605(){
+                new Class606();
+        }
+}
+class Class606 {
+        public Class606(){
+                new Class607();
+        }
+}
+class Class607 {
+        public Class607(){
+                new Class608();
+        }
+}
+class Class608 {
+        public Class608(){
+                new Class609();
+        }
+}
+class Class609 {
+        public Class609(){
+                new Class610();
+        }
+}
+class Class610 {
+        public Class610(){
+                new Class611();
+        }
+}
+class Class611 {
+        public Class611(){
+                new Class612();
+        }
+}
+class Class612 {
+        public Class612(){
+                new Class613();
+        }
+}
+class Class613 {
+        public Class613(){
+                new Class614();
+        }
+}
+class Class614 {
+        public Class614(){
+                new Class615();
+        }
+}
+class Class615 {
+        public Class615(){
+                new Class616();
+        }
+}
+class Class616 {
+        public Class616(){
+                new Class617();
+        }
+}
+class Class617 {
+        public Class617(){
+                new Class618();
+        }
+}
+class Class618 {
+        public Class618(){
+                new Class619();
+        }
+}
+class Class619 {
+        public Class619(){
+                new Class620();
+        }
+}
+class Class620 {
+        public Class620(){
+                new Class621();
+        }
+}
+class Class621 {
+        public Class621(){
+                new Class622();
+        }
+}
+class Class622 {
+        public Class622(){
+                new Class623();
+        }
+}
+class Class623 {
+        public Class623(){
+                new Class624();
+        }
+}
+class Class624 {
+        public Class624(){
+                new Class625();
+        }
+}
+class Class625 {
+        public Class625(){
+                new Class626();
+        }
+}
+class Class626 {
+        public Class626(){
+                new Class627();
+        }
+}
+class Class627 {
+        public Class627(){
+                new Class628();
+        }
+}
+class Class628 {
+        public Class628(){
+                new Class629();
+        }
+}
+class Class629 {
+        public Class629(){
+                new Class630();
+        }
+}
+class Class630 {
+        public Class630(){
+                new Class631();
+        }
+}
+class Class631 {
+        public Class631(){
+                new Class632();
+        }
+}
+class Class632 {
+        public Class632(){
+                new Class633();
+        }
+}
+class Class633 {
+        public Class633(){
+                new Class634();
+        }
+}
+class Class634 {
+        public Class634(){
+                new Class635();
+        }
+}
+class Class635 {
+        public Class635(){
+                new Class636();
+        }
+}
+class Class636 {
+        public Class636(){
+                new Class637();
+        }
+}
+class Class637 {
+        public Class637(){
+                new Class638();
+        }
+}
+class Class638 {
+        public Class638(){
+                new Class639();
+        }
+}
+class Class639 {
+        public Class639(){
+                new Class640();
+        }
+}
+class Class640 {
+        public Class640(){
+                new Class641();
+        }
+}
+class Class641 {
+        public Class641(){
+                new Class642();
+        }
+}
+class Class642 {
+        public Class642(){
+                new Class643();
+        }
+}
+class Class643 {
+        public Class643(){
+                new Class644();
+        }
+}
+class Class644 {
+        public Class644(){
+                new Class645();
+        }
+}
+class Class645 {
+        public Class645(){
+                new Class646();
+        }
+}
+class Class646 {
+        public Class646(){
+                new Class647();
+        }
+}
+class Class647 {
+        public Class647(){
+                new Class648();
+        }
+}
+class Class648 {
+        public Class648(){
+                new Class649();
+        }
+}
+class Class649 {
+        public Class649(){
+                new Class650();
+        }
+}
+class Class650 {
+        public Class650(){
+                new Class651();
+        }
+}
+class Class651 {
+        public Class651(){
+                new Class652();
+        }
+}
+class Class652 {
+        public Class652(){
+                new Class653();
+        }
+}
+class Class653 {
+        public Class653(){
+                new Class654();
+        }
+}
+class Class654 {
+        public Class654(){
+                new Class655();
+        }
+}
+class Class655 {
+        public Class655(){
+                new Class656();
+        }
+}
+class Class656 {
+        public Class656(){
+                new Class657();
+        }
+}
+class Class657 {
+        public Class657(){
+                new Class658();
+        }
+}
+class Class658 {
+        public Class658(){
+                new Class659();
+        }
+}
+class Class659 {
+        public Class659(){
+                new Class660();
+        }
+}
+class Class660 {
+        public Class660(){
+                new Class661();
+        }
+}
+class Class661 {
+        public Class661(){
+                new Class662();
+        }
+}
+class Class662 {
+        public Class662(){
+                new Class663();
+        }
+}
+class Class663 {
+        public Class663(){
+                new Class664();
+        }
+}
+class Class664 {
+        public Class664(){
+                new Class665();
+        }
+}
+class Class665 {
+        public Class665(){
+                new Class666();
+        }
+}
+class Class666 {
+        public Class666(){
+                new Class667();
+        }
+}
+class Class667 {
+        public Class667(){
+                new Class668();
+        }
+}
+class Class668 {
+        public Class668(){
+                new Class669();
+        }
+}
+class Class669 {
+        public Class669(){
+                new Class670();
+        }
+}
+class Class670 {
+        public Class670(){
+                new Class671();
+        }
+}
+class Class671 {
+        public Class671(){
+                new Class672();
+        }
+}
+class Class672 {
+        public Class672(){
+                new Class673();
+        }
+}
+class Class673 {
+        public Class673(){
+                new Class674();
+        }
+}
+class Class674 {
+        public Class674(){
+                new Class675();
+        }
+}
+class Class675 {
+        public Class675(){
+                new Class676();
+        }
+}
+class Class676 {
+        public Class676(){
+                new Class677();
+        }
+}
+class Class677 {
+        public Class677(){
+                new Class678();
+        }
+}
+class Class678 {
+        public Class678(){
+                new Class679();
+        }
+}
+class Class679 {
+        public Class679(){
+                new Class680();
+        }
+}
+class Class680 {
+        public Class680(){
+                new Class681();
+        }
+}
+class Class681 {
+        public Class681(){
+                new Class682();
+        }
+}
+class Class682 {
+        public Class682(){
+                new Class683();
+        }
+}
+class Class683 {
+        public Class683(){
+                new Class684();
+        }
+}
+class Class684 {
+        public Class684(){
+                new Class685();
+        }
+}
+class Class685 {
+        public Class685(){
+                new Class686();
+        }
+}
+class Class686 {
+        public Class686(){
+                new Class687();
+        }
+}
+class Class687 {
+        public Class687(){
+                new Class688();
+        }
+}
+class Class688 {
+        public Class688(){
+                new Class689();
+        }
+}
+class Class689 {
+        public Class689(){
+                new Class690();
+        }
+}
+class Class690 {
+        public Class690(){
+                new Class691();
+        }
+}
+class Class691 {
+        public Class691(){
+                new Class692();
+        }
+}
+class Class692 {
+        public Class692(){
+                new Class693();
+        }
+}
+class Class693 {
+        public Class693(){
+                new Class694();
+        }
+}
+class Class694 {
+        public Class694(){
+                new Class695();
+        }
+}
+class Class695 {
+        public Class695(){
+                new Class696();
+        }
+}
+class Class696 {
+        public Class696(){
+                new Class697();
+        }
+}
+class Class697 {
+        public Class697(){
+                new Class698();
+        }
+}
+class Class698 {
+        public Class698(){
+                new Class699();
+        }
+}
+class Class699 {
+        public Class699(){
+                new Class700();
+        }
+}
+class Class700 {
+        public Class700(){
+                new Class701();
+        }
+}
+class Class701 {
+        public Class701(){
+                new Class702();
+        }
+}
+class Class702 {
+        public Class702(){
+                new Class703();
+        }
+}
+class Class703 {
+        public Class703(){
+                new Class704();
+        }
+}
+class Class704 {
+        public Class704(){
+                new Class705();
+        }
+}
+class Class705 {
+        public Class705(){
+                new Class706();
+        }
+}
+class Class706 {
+        public Class706(){
+                new Class707();
+        }
+}
+class Class707 {
+        public Class707(){
+                new Class708();
+        }
+}
+class Class708 {
+        public Class708(){
+                new Class709();
+        }
+}
+class Class709 {
+        public Class709(){
+                new Class710();
+        }
+}
+class Class710 {
+        public Class710(){
+                new Class711();
+        }
+}
+class Class711 {
+        public Class711(){
+                new Class712();
+        }
+}
+class Class712 {
+        public Class712(){
+                new Class713();
+        }
+}
+class Class713 {
+        public Class713(){
+                new Class714();
+        }
+}
+class Class714 {
+        public Class714(){
+                new Class715();
+        }
+}
+class Class715 {
+        public Class715(){
+                new Class716();
+        }
+}
+class Class716 {
+        public Class716(){
+                new Class717();
+        }
+}
+class Class717 {
+        public Class717(){
+                new Class718();
+        }
+}
+class Class718 {
+        public Class718(){
+                new Class719();
+        }
+}
+class Class719 {
+        public Class719(){
+                new Class720();
+        }
+}
+class Class720 {
+        public Class720(){
+                new Class721();
+        }
+}
+class Class721 {
+        public Class721(){
+                new Class722();
+        }
+}
+class Class722 {
+        public Class722(){
+                new Class723();
+        }
+}
+class Class723 {
+        public Class723(){
+                new Class724();
+        }
+}
+class Class724 {
+        public Class724(){
+                new Class725();
+        }
+}
+class Class725 {
+        public Class725(){
+                new Class726();
+        }
+}
+class Class726 {
+        public Class726(){
+                new Class727();
+        }
+}
+class Class727 {
+        public Class727(){
+                new Class728();
+        }
+}
+class Class728 {
+        public Class728(){
+                new Class729();
+        }
+}
+class Class729 {
+        public Class729(){
+                new Class730();
+        }
+}
+class Class730 {
+        public Class730(){
+                new Class731();
+        }
+}
+class Class731 {
+        public Class731(){
+                new Class732();
+        }
+}
+class Class732 {
+        public Class732(){
+                new Class733();
+        }
+}
+class Class733 {
+        public Class733(){
+                new Class734();
+        }
+}
+class Class734 {
+        public Class734(){
+                new Class735();
+        }
+}
+class Class735 {
+        public Class735(){
+                new Class736();
+        }
+}
+class Class736 {
+        public Class736(){
+                new Class737();
+        }
+}
+class Class737 {
+        public Class737(){
+                new Class738();
+        }
+}
+class Class738 {
+        public Class738(){
+                new Class739();
+        }
+}
+class Class739 {
+        public Class739(){
+                new Class740();
+        }
+}
+class Class740 {
+        public Class740(){
+                new Class741();
+        }
+}
+class Class741 {
+        public Class741(){
+                new Class742();
+        }
+}
+class Class742 {
+        public Class742(){
+                new Class743();
+        }
+}
+class Class743 {
+        public Class743(){
+                new Class744();
+        }
+}
+class Class744 {
+        public Class744(){
+                new Class745();
+        }
+}
+class Class745 {
+        public Class745(){
+                new Class746();
+        }
+}
+class Class746 {
+        public Class746(){
+                new Class747();
+        }
+}
+class Class747 {
+        public Class747(){
+                new Class748();
+        }
+}
+class Class748 {
+        public Class748(){
+                new Class749();
+        }
+}
+class Class749 {
+        public Class749(){
+                new Class750();
+        }
+}
+class Class750 {
+        public Class750(){
+                new Class751();
+        }
+}
+class Class751 {
+        public Class751(){
+                new Class752();
+        }
+}
+class Class752 {
+        public Class752(){
+                new Class753();
+        }
+}
+class Class753 {
+        public Class753(){
+                new Class754();
+        }
+}
+class Class754 {
+        public Class754(){
+                new Class755();
+        }
+}
+class Class755 {
+        public Class755(){
+                new Class756();
+        }
+}
+class Class756 {
+        public Class756(){
+                new Class757();
+        }
+}
+class Class757 {
+        public Class757(){
+                new Class758();
+        }
+}
+class Class758 {
+        public Class758(){
+                new Class759();
+        }
+}
+class Class759 {
+        public Class759(){
+                new Class760();
+        }
+}
+class Class760 {
+        public Class760(){
+                new Class761();
+        }
+}
+class Class761 {
+        public Class761(){
+                new Class762();
+        }
+}
+class Class762 {
+        public Class762(){
+                new Class763();
+        }
+}
+class Class763 {
+        public Class763(){
+                new Class764();
+        }
+}
+class Class764 {
+        public Class764(){
+                new Class765();
+        }
+}
+class Class765 {
+        public Class765(){
+                new Class766();
+        }
+}
+class Class766 {
+        public Class766(){
+                new Class767();
+        }
+}
+class Class767 {
+        public Class767(){
+                new Class768();
+        }
+}
+class Class768 {
+        public Class768(){
+                new Class769();
+        }
+}
+class Class769 {
+        public Class769(){
+                new Class770();
+        }
+}
+class Class770 {
+        public Class770(){
+                new Class771();
+        }
+}
+class Class771 {
+        public Class771(){
+                new Class772();
+        }
+}
+class Class772 {
+        public Class772(){
+                new Class773();
+        }
+}
+class Class773 {
+        public Class773(){
+                new Class774();
+        }
+}
+class Class774 {
+        public Class774(){
+                new Class775();
+        }
+}
+class Class775 {
+        public Class775(){
+                new Class776();
+        }
+}
+class Class776 {
+        public Class776(){
+                new Class777();
+        }
+}
+class Class777 {
+        public Class777(){
+                new Class778();
+        }
+}
+class Class778 {
+        public Class778(){
+                new Class779();
+        }
+}
+class Class779 {
+        public Class779(){
+                new Class780();
+        }
+}
+class Class780 {
+        public Class780(){
+                new Class781();
+        }
+}
+class Class781 {
+        public Class781(){
+                new Class782();
+        }
+}
+class Class782 {
+        public Class782(){
+                new Class783();
+        }
+}
+class Class783 {
+        public Class783(){
+                new Class784();
+        }
+}
+class Class784 {
+        public Class784(){
+                new Class785();
+        }
+}
+class Class785 {
+        public Class785(){
+                new Class786();
+        }
+}
+class Class786 {
+        public Class786(){
+                new Class787();
+        }
+}
+class Class787 {
+        public Class787(){
+                new Class788();
+        }
+}
+class Class788 {
+        public Class788(){
+                new Class789();
+        }
+}
+class Class789 {
+        public Class789(){
+                new Class790();
+        }
+}
+class Class790 {
+        public Class790(){
+                new Class791();
+        }
+}
+class Class791 {
+        public Class791(){
+                new Class792();
+        }
+}
+class Class792 {
+        public Class792(){
+                new Class793();
+        }
+}
+class Class793 {
+        public Class793(){
+                new Class794();
+        }
+}
+class Class794 {
+        public Class794(){
+                new Class795();
+        }
+}
+class Class795 {
+        public Class795(){
+                new Class796();
+        }
+}
+class Class796 {
+        public Class796(){
+                new Class797();
+        }
+}
+class Class797 {
+        public Class797(){
+                new Class798();
+        }
+}
+class Class798 {
+        public Class798(){
+                new Class799();
+        }
+}
+class Class799 {
+        public Class799(){
+                new Class800();
+        }
+}
+class Class800 {
+        public Class800(){
+                new Class801();
+        }
+}
+class Class801 {
+        public Class801(){
+                new Class802();
+        }
+}
+class Class802 {
+        public Class802(){
+                new Class803();
+        }
+}
+class Class803 {
+        public Class803(){
+                new Class804();
+        }
+}
+class Class804 {
+        public Class804(){
+                new Class805();
+        }
+}
+class Class805 {
+        public Class805(){
+                new Class806();
+        }
+}
+class Class806 {
+        public Class806(){
+                new Class807();
+        }
+}
+class Class807 {
+        public Class807(){
+                new Class808();
+        }
+}
+class Class808 {
+        public Class808(){
+                new Class809();
+        }
+}
+class Class809 {
+        public Class809(){
+                new Class810();
+        }
+}
+class Class810 {
+        public Class810(){
+                new Class811();
+        }
+}
+class Class811 {
+        public Class811(){
+                new Class812();
+        }
+}
+class Class812 {
+        public Class812(){
+                new Class813();
+        }
+}
+class Class813 {
+        public Class813(){
+                new Class814();
+        }
+}
+class Class814 {
+        public Class814(){
+                new Class815();
+        }
+}
+class Class815 {
+        public Class815(){
+                new Class816();
+        }
+}
+class Class816 {
+        public Class816(){
+                new Class817();
+        }
+}
+class Class817 {
+        public Class817(){
+                new Class818();
+        }
+}
+class Class818 {
+        public Class818(){
+                new Class819();
+        }
+}
+class Class819 {
+        public Class819(){
+                new Class820();
+        }
+}
+class Class820 {
+        public Class820(){
+                new Class821();
+        }
+}
+class Class821 {
+        public Class821(){
+                new Class822();
+        }
+}
+class Class822 {
+        public Class822(){
+                new Class823();
+        }
+}
+class Class823 {
+        public Class823(){
+                new Class824();
+        }
+}
+class Class824 {
+        public Class824(){
+                new Class825();
+        }
+}
+class Class825 {
+        public Class825(){
+                new Class826();
+        }
+}
+class Class826 {
+        public Class826(){
+                new Class827();
+        }
+}
+class Class827 {
+        public Class827(){
+                new Class828();
+        }
+}
+class Class828 {
+        public Class828(){
+                new Class829();
+        }
+}
+class Class829 {
+        public Class829(){
+                new Class830();
+        }
+}
+class Class830 {
+        public Class830(){
+                new Class831();
+        }
+}
+class Class831 {
+        public Class831(){
+                new Class832();
+        }
+}
+class Class832 {
+        public Class832(){
+                new Class833();
+        }
+}
+class Class833 {
+        public Class833(){
+                new Class834();
+        }
+}
+class Class834 {
+        public Class834(){
+                new Class835();
+        }
+}
+class Class835 {
+        public Class835(){
+                new Class836();
+        }
+}
+class Class836 {
+        public Class836(){
+                new Class837();
+        }
+}
+class Class837 {
+        public Class837(){
+                new Class838();
+        }
+}
+class Class838 {
+        public Class838(){
+                new Class839();
+        }
+}
+class Class839 {
+        public Class839(){
+                new Class840();
+        }
+}
+class Class840 {
+        public Class840(){
+                new Class841();
+        }
+}
+class Class841 {
+        public Class841(){
+                new Class842();
+        }
+}
+class Class842 {
+        public Class842(){
+                new Class843();
+        }
+}
+class Class843 {
+        public Class843(){
+                new Class844();
+        }
+}
+class Class844 {
+        public Class844(){
+                new Class845();
+        }
+}
+class Class845 {
+        public Class845(){
+                new Class846();
+        }
+}
+class Class846 {
+        public Class846(){
+                new Class847();
+        }
+}
+class Class847 {
+        public Class847(){
+                new Class848();
+        }
+}
+class Class848 {
+        public Class848(){
+                new Class849();
+        }
+}
+class Class849 {
+        public Class849(){
+                new Class850();
+        }
+}
+class Class850 {
+        public Class850(){
+                new Class851();
+        }
+}
+class Class851 {
+        public Class851(){
+                new Class852();
+        }
+}
+class Class852 {
+        public Class852(){
+                new Class853();
+        }
+}
+class Class853 {
+        public Class853(){
+                new Class854();
+        }
+}
+class Class854 {
+        public Class854(){
+                new Class855();
+        }
+}
+class Class855 {
+        public Class855(){
+                new Class856();
+        }
+}
+class Class856 {
+        public Class856(){
+                new Class857();
+        }
+}
+class Class857 {
+        public Class857(){
+                new Class858();
+        }
+}
+class Class858 {
+        public Class858(){
+                new Class859();
+        }
+}
+class Class859 {
+        public Class859(){
+                new Class860();
+        }
+}
+class Class860 {
+        public Class860(){
+                new Class861();
+        }
+}
+class Class861 {
+        public Class861(){
+                new Class862();
+        }
+}
+class Class862 {
+        public Class862(){
+                new Class863();
+        }
+}
+class Class863 {
+        public Class863(){
+                new Class864();
+        }
+}
+class Class864 {
+        public Class864(){
+                new Class865();
+        }
+}
+class Class865 {
+        public Class865(){
+                new Class866();
+        }
+}
+class Class866 {
+        public Class866(){
+                new Class867();
+        }
+}
+class Class867 {
+        public Class867(){
+                new Class868();
+        }
+}
+class Class868 {
+        public Class868(){
+                new Class869();
+        }
+}
+class Class869 {
+        public Class869(){
+                new Class870();
+        }
+}
+class Class870 {
+        public Class870(){
+                new Class871();
+        }
+}
+class Class871 {
+        public Class871(){
+                new Class872();
+        }
+}
+class Class872 {
+        public Class872(){
+                new Class873();
+        }
+}
+class Class873 {
+        public Class873(){
+                new Class874();
+        }
+}
+class Class874 {
+        public Class874(){
+                new Class875();
+        }
+}
+class Class875 {
+        public Class875(){
+                new Class876();
+        }
+}
+class Class876 {
+        public Class876(){
+                new Class877();
+        }
+}
+class Class877 {
+        public Class877(){
+                new Class878();
+        }
+}
+class Class878 {
+        public Class878(){
+                new Class879();
+        }
+}
+class Class879 {
+        public Class879(){
+                new Class880();
+        }
+}
+class Class880 {
+        public Class880(){
+                new Class881();
+        }
+}
+class Class881 {
+        public Class881(){
+                new Class882();
+        }
+}
+class Class882 {
+        public Class882(){
+                new Class883();
+        }
+}
+class Class883 {
+        public Class883(){
+                new Class884();
+        }
+}
+class Class884 {
+        public Class884(){
+                new Class885();
+        }
+}
+class Class885 {
+        public Class885(){
+                new Class886();
+        }
+}
+class Class886 {
+        public Class886(){
+                new Class887();
+        }
+}
+class Class887 {
+        public Class887(){
+                new Class888();
+        }
+}
+class Class888 {
+        public Class888(){
+                new Class889();
+        }
+}
+class Class889 {
+        public Class889(){
+                new Class890();
+        }
+}
+class Class890 {
+        public Class890(){
+                new Class891();
+        }
+}
+class Class891 {
+        public Class891(){
+                new Class892();
+        }
+}
+class Class892 {
+        public Class892(){
+                new Class893();
+        }
+}
+class Class893 {
+        public Class893(){
+                new Class894();
+        }
+}
+class Class894 {
+        public Class894(){
+                new Class895();
+        }
+}
+class Class895 {
+        public Class895(){
+                new Class896();
+        }
+}
+class Class896 {
+        public Class896(){
+                new Class897();
+        }
+}
+class Class897 {
+        public Class897(){
+                new Class898();
+        }
+}
+class Class898 {
+        public Class898(){
+                new Class899();
+        }
+}
+class Class899 {
+        public Class899(){
+                new Class900();
+        }
+}
+class Class900 {
+        public Class900(){
+                new Class901();
+        }
+}
+class Class901 {
+        public Class901(){
+                new Class902();
+        }
+}
+class Class902 {
+        public Class902(){
+                new Class903();
+        }
+}
+class Class903 {
+        public Class903(){
+                new Class904();
+        }
+}
+class Class904 {
+        public Class904(){
+                new Class905();
+        }
+}
+class Class905 {
+        public Class905(){
+                new Class906();
+        }
+}
+class Class906 {
+        public Class906(){
+                new Class907();
+        }
+}
+class Class907 {
+        public Class907(){
+                new Class908();
+        }
+}
+class Class908 {
+        public Class908(){
+                new Class909();
+        }
+}
+class Class909 {
+        public Class909(){
+                new Class910();
+        }
+}
+class Class910 {
+        public Class910(){
+                new Class911();
+        }
+}
+class Class911 {
+        public Class911(){
+                new Class912();
+        }
+}
+class Class912 {
+        public Class912(){
+                new Class913();
+        }
+}
+class Class913 {
+        public Class913(){
+                new Class914();
+        }
+}
+class Class914 {
+        public Class914(){
+                new Class915();
+        }
+}
+class Class915 {
+        public Class915(){
+                new Class916();
+        }
+}
+class Class916 {
+        public Class916(){
+                new Class917();
+        }
+}
+class Class917 {
+        public Class917(){
+                new Class918();
+        }
+}
+class Class918 {
+        public Class918(){
+                new Class919();
+        }
+}
+class Class919 {
+        public Class919(){
+                new Class920();
+        }
+}
+class Class920 {
+        public Class920(){
+                new Class921();
+        }
+}
+class Class921 {
+        public Class921(){
+                new Class922();
+        }
+}
+class Class922 {
+        public Class922(){
+                new Class923();
+        }
+}
+class Class923 {
+        public Class923(){
+                new Class924();
+        }
+}
+class Class924 {
+        public Class924(){
+                new Class925();
+        }
+}
+class Class925 {
+        public Class925(){
+                new Class926();
+        }
+}
+class Class926 {
+        public Class926(){
+                new Class927();
+        }
+}
+class Class927 {
+        public Class927(){
+                new Class928();
+        }
+}
+class Class928 {
+        public Class928(){
+                new Class929();
+        }
+}
+class Class929 {
+        public Class929(){
+                new Class930();
+        }
+}
+class Class930 {
+        public Class930(){
+                new Class931();
+        }
+}
+class Class931 {
+        public Class931(){
+                new Class932();
+        }
+}
+class Class932 {
+        public Class932(){
+                new Class933();
+        }
+}
+class Class933 {
+        public Class933(){
+                new Class934();
+        }
+}
+class Class934 {
+        public Class934(){
+                new Class935();
+        }
+}
+class Class935 {
+        public Class935(){
+                new Class936();
+        }
+}
+class Class936 {
+        public Class936(){
+                new Class937();
+        }
+}
+class Class937 {
+        public Class937(){
+                new Class938();
+        }
+}
+class Class938 {
+        public Class938(){
+                new Class939();
+        }
+}
+class Class939 {
+        public Class939(){
+                new Class940();
+        }
+}
+class Class940 {
+        public Class940(){
+                new Class941();
+        }
+}
+class Class941 {
+        public Class941(){
+                new Class942();
+        }
+}
+class Class942 {
+        public Class942(){
+                new Class943();
+        }
+}
+class Class943 {
+        public Class943(){
+                new Class944();
+        }
+}
+class Class944 {
+        public Class944(){
+                new Class945();
+        }
+}
+class Class945 {
+        public Class945(){
+                new Class946();
+        }
+}
+class Class946 {
+        public Class946(){
+                new Class947();
+        }
+}
+class Class947 {
+        public Class947(){
+                new Class948();
+        }
+}
+class Class948 {
+        public Class948(){
+                new Class949();
+        }
+}
+class Class949 {
+        public Class949(){
+                new Class950();
+        }
+}
+class Class950 {
+        public Class950(){
+                new Class951();
+        }
+}
+class Class951 {
+        public Class951(){
+                new Class952();
+        }
+}
+class Class952 {
+        public Class952(){
+                new Class953();
+        }
+}
+class Class953 {
+        public Class953(){
+                new Class954();
+        }
+}
+class Class954 {
+        public Class954(){
+                new Class955();
+        }
+}
+class Class955 {
+        public Class955(){
+                new Class956();
+        }
+}
+class Class956 {
+        public Class956(){
+                new Class957();
+        }
+}
+class Class957 {
+        public Class957(){
+                new Class958();
+        }
+}
+class Class958 {
+        public Class958(){
+                new Class959();
+        }
+}
+class Class959 {
+        public Class959(){
+                new Class960();
+        }
+}
+class Class960 {
+        public Class960(){
+                new Class961();
+        }
+}
+class Class961 {
+        public Class961(){
+                new Class962();
+        }
+}
+class Class962 {
+        public Class962(){
+                new Class963();
+        }
+}
+class Class963 {
+        public Class963(){
+                new Class964();
+        }
+}
+class Class964 {
+        public Class964(){
+                new Class965();
+        }
+}
+class Class965 {
+        public Class965(){
+                new Class966();
+        }
+}
+class Class966 {
+        public Class966(){
+                new Class967();
+        }
+}
+class Class967 {
+        public Class967(){
+                new Class968();
+        }
+}
+class Class968 {
+        public Class968(){
+                new Class969();
+        }
+}
+class Class969 {
+        public Class969(){
+                new Class970();
+        }
+}
+class Class970 {
+        public Class970(){
+                new Class971();
+        }
+}
+class Class971 {
+        public Class971(){
+                new Class972();
+        }
+}
+class Class972 {
+        public Class972(){
+                new Class973();
+        }
+}
+class Class973 {
+        public Class973(){
+                new Class974();
+        }
+}
+class Class974 {
+        public Class974(){
+                new Class975();
+        }
+}
+class Class975 {
+        public Class975(){
+                new Class976();
+        }
+}
+class Class976 {
+        public Class976(){
+                new Class977();
+        }
+}
+class Class977 {
+        public Class977(){
+                new Class978();
+        }
+}
+class Class978 {
+        public Class978(){
+                new Class979();
+        }
+}
+class Class979 {
+        public Class979(){
+                new Class980();
+        }
+}
+class Class980 {
+        public Class980(){
+                new Class981();
+        }
+}
+class Class981 {
+        public Class981(){
+                new Class982();
+        }
+}
+class Class982 {
+        public Class982(){
+                new Class983();
+        }
+}
+class Class983 {
+        public Class983(){
+                new Class984();
+        }
+}
+class Class984 {
+        public Class984(){
+                new Class985();
+        }
+}
+class Class985 {
+        public Class985(){
+                new Class986();
+        }
+}
+class Class986 {
+        public Class986(){
+                new Class987();
+        }
+}
+class Class987 {
+        public Class987(){
+                new Class988();
+        }
+}
+class Class988 {
+        public Class988(){
+                new Class989();
+        }
+}
+class Class989 {
+        public Class989(){
+                new Class990();
+        }
+}
+class Class990 {
+        public Class990(){
+                new Class991();
+        }
+}
+class Class991 {
+        public Class991(){
+                new Class992();
+        }
+}
+class Class992 {
+        public Class992(){
+                new Class993();
+        }
+}
+class Class993 {
+        public Class993(){
+                new Class994();
+        }
+}
+class Class994 {
+        public Class994(){
+                new Class995();
+        }
+}
+class Class995 {
+        public Class995(){
+                new Class996();
+        }
+}
+class Class996 {
+        public Class996(){
+                new Class997();
+        }
+}
+class Class997 {
+        public Class997(){
+                new Class998();
+        }
+}
+class Class998 {
+        public Class998(){
+                new Class999();
+        }
+}
+class Class999 {
+        public Class999(){
+                new Class1000();
+        }
+}
+class Class1000 {
+        public Class1000(){
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinDiag.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.runner.RunParams;
+
+/**
+ *  Helper that prints information about FinMemoryObjects.
+ */
+public class FinDiag implements Runnable {
+        private long sleepTime;
+
+        public FinDiag() {
+                this(RunParams.getInstance().getSleepTime());
+        }
+
+        public FinDiag(long sleepTime) {
+                this.sleepTime = sleepTime;
+        }
+
+        public void run() {
+                FinMemoryObject.dumpStatistics();
+                // Ensure that interrupt status is not lost
+                if (Thread.currentThread().isInterrupted())
+                        return;
+                try {
+                        Thread.sleep(sleepTime);
+                } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinMemoryObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.PrintStream;
+
+/**
+ * An object that occupies approximately given number of bytes in memory
+ * and also records number of allocated and finalized instances.
+ */
+public class FinMemoryObject extends FinMemoryObject1 {
+        private static int finalizedCount;
+
+        public FinMemoryObject(int size) {
+                super(size);
+        }
+
+        protected void finalize() {
+                synchronized (FinMemoryObject.class) {
+                        ++finalizedCount;
+                }
+        }
+
+        /**
+         * Returns the number of finalized FinMemoryObjects.
+         */
+        public static int getFinalizedCount() {
+                return finalizedCount;
+        }
+
+        /**
+         * Returns the number of live FinMemoryObjects (allocated but not finalized).
+         */
+        public static int getLiveCount() {
+                return allocatedCount - finalizedCount;
+        }
+
+        public static void dumpStatistics(PrintStream out) {
+                Algorithms.tryToPrintln(out, "Object count: " + getLiveCount());
+        }
+
+        public static void dumpStatistics() {
+                dumpStatistics(System.out);
+        }
+
+        public static boolean isAllFinalized() {
+                return getLiveCount() == 0;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/FinMemoryObject1.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.PrintStream;
+import nsk.share.gc.Algorithms;
+
+/**
+ * An object that occupies approximately given number of bytes in memory
+ * and also has finalizer that does nothing.
+ */
+public class FinMemoryObject1 extends MemoryObject {
+        protected static int allocatedCount;
+
+        public FinMemoryObject1(int size) {
+                super(size);
+                synchronized (FinMemoryObject.class) {
+                        ++allocatedCount;
+                }
+        }
+
+        protected void finalize() {
+        }
+
+        /**
+         * Returns the number of allocated FinMemoryObjects.
+         */
+        public static int getAllocatedCount() {
+                return allocatedCount;
+        }
+
+        public static void dumpStatistics(PrintStream out) {
+                Algorithms.tryToPrintln(out, "Object count: " + getAllocatedCount());
+        }
+
+        public static void dumpStatistics() {
+                dumpStatistics(System.out);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GC.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.test.*;
+import nsk.share.runner.*;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.GarbageProducerAware;
+import nsk.share.gc.gp.GarbageProducer1Aware;
+import nsk.share.gc.gp.MemoryStrategy;
+import nsk.share.gc.gp.MemoryStrategyAware;
+import nsk.share.gc.gp.GarbageUtils;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.LockersAware;
+import nsk.share.gc.lock.LockerUtils;
+
+/**
+ * Utility methods for GC tests.
+ */
+public class GC extends nsk.share.test.Tests {
+        protected static class GCTestRunner extends TestRunner {
+                private GCParams gcParams;
+                private GarbageProducer garbageProducer;
+                private GarbageProducer garbageProducer1;
+                private MemoryStrategy memoryStrategy;
+                private Lockers lockers;
+
+                public GCTestRunner(Test test, String[] args) {
+                        super(test, args);
+                }
+
+                private GCParams getGCParams(String[] args) {
+                        if (gcParams == null) {
+                                gcParams = GCParams.getInstance();
+                                gcParams.parseCommandLine(args);
+                        }
+                        return gcParams;
+                }
+
+                private GarbageProducer getGarbageProducer(String[] args) {
+                        if (garbageProducer == null) {
+                                garbageProducer = GarbageUtils.getGarbageProducer(getGCParams(args).getGarbageProducerId());
+                                configure(garbageProducer);
+                        }
+                        return garbageProducer;
+                }
+
+                private GarbageProducer getGarbageProducer1(String[] args) {
+                        if (garbageProducer1 == null) {
+                                garbageProducer1 = GarbageUtils.getGarbageProducer(getGCParams(args).getGarbageProducer1Id());
+                                configure(garbageProducer1);
+                        }
+                        return garbageProducer1;
+                }
+
+                private MemoryStrategy getMemoryStrategy(String[] args) {
+                        if (memoryStrategy == null) {
+                                memoryStrategy = MemoryStrategy.fromString(getGCParams(args).getMemoryStrategyId());
+                                configure(memoryStrategy);
+                        }
+                        return memoryStrategy;
+                }
+
+                private Lockers getLockers(String[] args) {
+                        if (lockers == null) {
+                                lockers = LockerUtils.getLockers(getGCParams(args).getLockersId());
+                                configure(lockers);
+                        }
+                        return lockers;
+                }
+
+                public void configure(Object test) {
+                        super.configure(test);
+                        if (test instanceof GCParamsAware)
+                                ((GCParamsAware) test).setGCParams(getGCParams(args));
+                        if (test instanceof GarbageProducerAware)
+                                ((GarbageProducerAware) test).setGarbageProducer(getGarbageProducer(args));
+                        if (test instanceof GarbageProducer1Aware)
+                                ((GarbageProducer1Aware) test).setGarbageProducer1(getGarbageProducer1(args));
+                        if (test instanceof MemoryStrategyAware)
+                                ((MemoryStrategyAware) test).setMemoryStrategy(getMemoryStrategy(args));
+                        if (test instanceof LockersAware)
+                                ((LockersAware) test).setLockers(getLockers(args));
+                }
+
+
+        }
+
+        private GC() {
+        }
+
+        public static void runTest(Test test, String[] args) {
+                new GCTestRunner(test, args).run();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParams.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.PrintStream;
+
+public class GCParams {
+        private String garbageProducerId;
+        private String garbageProducer1Id;
+        private String memoryStrategyId;
+        private String lockersId;
+
+        public final String getGarbageProducerId() {
+                return garbageProducerId;
+        }
+
+        public final void setGarbageProducerId(String garbageProducerId) {
+                this.garbageProducerId = garbageProducerId;
+        }
+
+        public final String getGarbageProducer1Id() {
+                return garbageProducer1Id;
+        }
+
+        public final void setGarbageProducer1Id(String garbageProducer1Id) {
+                this.garbageProducer1Id = garbageProducer1Id;
+        }
+
+        public final String getMemoryStrategyId() {
+                return memoryStrategyId;
+        }
+
+        public final void setMemoryStrategyId(String memoryStrategyId) {
+                this.memoryStrategyId = memoryStrategyId;
+        }
+
+        public final String getLockersId() {
+                return lockersId;
+        }
+
+        public final void setLockersId(String lockersId) {
+                this.lockersId = lockersId;
+        }
+
+        public void parseCommandLine(String[] args) {
+                if (args == null)
+                        return;
+                for (int i = 0; i < args.length; ++i) {
+                        if (args[i].equals("-gp"))
+                                garbageProducerId = args[++i];
+                        else if (args[i].equals("-gp1"))
+                                garbageProducer1Id = args[++i];
+                        else if (args[i].equals("-ms"))
+                                memoryStrategyId = args[++i];
+                        else if (args[i].equals("-lockers"))
+                                lockersId = args[++i];
+                }
+                printConfig(System.out);
+        }
+
+        public void prinUsage() {
+        }
+
+        public void printConfig(PrintStream out) {
+        }
+
+        private static GCParams instance;
+
+        public static GCParams getInstance() {
+                synchronized (GCParams.class) {
+                        if (instance == null)
+                                instance = new GCParams();
+                        return instance;
+                }
+        }
+
+        public static void setInstance(GCParams gcParams) {
+                synchronized (GCParams.class) {
+                        instance = gcParams;
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCParamsAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+/**
+ * Marker interface to signify that run params are needed.
+ */
+public interface GCParamsAware {
+        public void setGCParams(GCParams gcParams);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/GCTestBase.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.test.TestBase;
+import nsk.share.runner.RunParams;
+import nsk.share.runner.RunParamsAware;
+
+public abstract class GCTestBase extends TestBase implements RunParamsAware, GCParamsAware {
+        protected RunParams runParams;
+        protected GCParams gcParams;
+
+        public final void setRunParams(RunParams runParams) {
+                this.runParams = runParams;
+        }
+
+        public final void setGCParams(GCParams gcParams) {
+                this.gcParams = gcParams;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/IndexPair.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+public final class IndexPair {
+        private int i, j;
+
+        public IndexPair(int i, int j) {
+                setI(i);
+                setJ(j);
+        }
+
+        public int getI() {
+                return i;
+        }
+
+        public void setI(int i) {
+                this.i = i;
+        }
+
+        public int getJ() {
+                return j;
+        }
+
+        public void setJ(int j) {
+                this.j = j;
+        }
+
+        public boolean equals(IndexPair pair) {
+                return (this.i == pair.i && this.j == pair.j);
+        }
+
+        public boolean equals(Object o) {
+                return o instanceof IndexPair && equals((IndexPair) o);
+        }
+
+        public int hashCode() {
+                return i << 16 + j;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/LinkedMemoryObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+/**
+ *  An object that occupies approximately given number of bytes in memory
+ *  and has forward and backward links to other objects.
+ */
+public class LinkedMemoryObject extends MemoryObject {
+        private LinkedMemoryObject next;
+        private LinkedMemoryObject prev;
+
+        /**
+         *  Create an object that occupies given number of bytes.
+         *
+         *  @param arraySize size
+         */
+        public LinkedMemoryObject(int size) {
+                super(size - 2 * Memory.getReferenceSize());
+        }
+
+        public LinkedMemoryObject(int size, LinkedMemoryObject next) {
+                super(size - 2 * Memory.getReferenceSize());
+                setNext(next);
+        }
+
+        public LinkedMemoryObject(int size, LinkedMemoryObject next, LinkedMemoryObject prev) {
+                super(size - 2 * Memory.getReferenceSize());
+                setNext(next);
+                setPrev(prev);
+        }
+
+        public final void setNext(LinkedMemoryObject next) {
+                this.next = next;
+        }
+
+        public final void setPrev(LinkedMemoryObject prev) {
+                this.prev = prev;
+        }
+
+        public final LinkedMemoryObject getNext() {
+                return next;
+        }
+
+        public final LinkedMemoryObject getPrev() {
+                return prev;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Matrix.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+public class Matrix {
+        private int cellSize;
+        private int matrixSize;
+        private Cell matrix[][];
+        private int nKnockedOut; // number of cells "nulled out"
+
+        public Matrix(int matrixSize, int cellSize) {
+                this.matrixSize = matrixSize;
+                this.cellSize = cellSize;
+                matrix = new Cell[matrixSize][matrixSize];
+                populate();
+        }
+
+        public void populate() {
+                for (int i = 0; i < matrixSize ; i++) {
+                        for( int j = 0 ; j < matrixSize ; j++) {
+                                matrix[i][j] = new Cell(cellSize, i);
+                        }
+                }
+        }
+
+        public int returnArrayBound() {
+                return matrixSize - 1;
+        }
+
+        public synchronized void clear(int i, int j) {
+                matrix[i][j] = null;
+                ++nKnockedOut;
+        }
+
+        public synchronized void repopulate(int i, int j) {
+                matrix[i][j] = new Cell(cellSize, i + j);
+                --nKnockedOut;
+        }
+
+        public synchronized void resetCellCount() {
+                nKnockedOut = 0;
+        }
+
+        public synchronized int getCellCount() {
+                return nKnockedOut;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.test.LocalRandom;
+import java.io.PrintStream;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.tree.*;
+import nsk.share.gc.gp.MemoryStrategy;
+import nsk.share.log.Log;
+
+/**
+ *  Different utility methods to work with memory objects.
+ */
+public final class Memory {
+        private static int bits = 0;
+        private static int referenceSize = 0;
+        private static int objectExtraSize = 0;
+
+        private Memory() {
+        }
+
+        private static int getBits() {
+                if (bits == 0)
+                        bits = Integer.parseInt(System.getProperty("sun.arch.data.model"));
+                return bits;
+        }
+
+        /**
+         *  Get size of one object reference.
+         *
+         *  TODO: somehow determine the real value
+         */
+        public static int getReferenceSize() {
+                if (referenceSize == 0)
+                        referenceSize = (getBits() == 64) ? 8 : 4;
+                return referenceSize;
+        }
+
+        /**
+         * Get size of primitive type int.
+         */
+        public static int getIntSize() {
+                return 4;
+        }
+
+        /**
+         * Get size of primitive type boolean.
+         */
+        public static int getBooleanSize() {
+                return 1;
+        }
+
+        /**
+         * Get size of primitive type byte.
+         */
+        public static int getByteSize() {
+                return 1;
+        }
+
+        /**
+         * Get size of primitive type char.
+         */
+        public static int getCharSize() {
+                return 2;
+        }
+
+        /**
+         * Get size of primitive type short.
+         */
+        public static int getShortSize() {
+                return 2;
+        }
+
+        /**
+         * Get size of primitive type long.
+         */
+        public static int getLongSize() {
+                return 8;
+        }
+
+        /**
+         * Get size of primitive type float.
+         */
+        public static int getFloatSize() {
+                return 4;
+        }
+
+        /**
+         * Get size of primitive type double.
+         */
+        public static int getDoubleSize() {
+                return 8;
+        }
+
+        /**
+         *  Get how many extra bytes an object occupies in the heap
+         *  compared to sum of it's fields.
+         *
+         *  TODO: somehow determine the real value
+         */
+        public static int getObjectExtraSize() {
+                if (objectExtraSize == 0)
+                        objectExtraSize = 2 * getReferenceSize();
+                return objectExtraSize;
+        }
+        /**
+         *  Get how many extra bytes an array occupies in the heap
+         *  compared to sum of it's fields.
+         *
+         *  TODO: somehow determine the real value
+         */
+        public static int getArrayExtraSize() {
+                return getObjectExtraSize();
+        }
+
+        /**
+         * Return size of reference object (SoftReference, WeakReference, PhantomReference)
+         */
+        public static int getReferenceObjectSize() {
+                return getReferenceSize() + getObjectExtraSize();
+        }
+
+        /**
+         *  Get an approximate length of array that will occupy a given memory.
+         *
+         *  @param memory size of memory
+         *  @param objectSize size of each object in array
+         *  @return length of array
+         */
+        public static int getArrayLength(long memory, long objectSize) {
+                int referenceSize = getReferenceSize();
+                int arrayExtraSize = getArrayExtraSize();
+                return (int) Math.min(
+                                (memory - arrayExtraSize) / (objectSize + referenceSize),
+                                Integer.MAX_VALUE
+                                );
+        }
+
+        /**
+         *  Get an approximate size of array of given length and object size.
+         *
+         *  @param length length of arary
+         *  @param objectSize size of object in array
+         *  @return size of array
+         */
+        public static long getArraySize(int length, long objectSize) {
+                return getObjectExtraSize() + length * (objectSize + getReferenceSize());
+        }
+
+        /**
+         *  Calculate approximate size of biggest of MemoryObjects.
+         */
+        public static long getMemoryObjectSize(long size) {
+                return size + 2 * getReferenceSize() + getObjectExtraSize();
+        }
+
+        /**
+         *  Calculate approximate size of linked list in memory.
+         *
+         *  @param length length of list
+         *  @param size size of object
+         *  @return size
+         */
+        public static long getListSize(int length, int size) {
+                return getObjectExtraSize() + length * (getReferenceSize() + getMemoryObjectSize(size));
+        }
+
+        /**
+         *  Calculate length of linear or circular linked list.
+         *
+         *  @param mobj head of list
+         *  @return length of list
+         */
+        public static int getListLength(LinkedMemoryObject mobj) {
+                LinkedMemoryObject tobj = mobj;
+                int length = 0;
+                do {
+                        ++length;
+                        tobj = tobj.getNext();
+                } while (tobj != null && tobj != mobj);
+                return length;
+        }
+
+        /**
+         *  Calculate length of array of linear or circular linked lists.
+         *
+         *  @param mobjs array containting heads of lists
+         *  @return length of all lists
+         */
+        public static int getListsLength(LinkedMemoryObject[] mobjs) {
+                int length = 0;
+                for (int i = 0; i < mobjs.length; ++i) {
+                        LinkedMemoryObject mobj = mobjs[i];
+                        if (mobj != null)
+                                length += getListLength(mobj);
+                }
+                return length;
+        }
+
+        /**
+         *  Calculate size of all objects in linear or circular linked list.
+         *
+         *  @param mobj head of list
+         *  @return size of list
+         */
+        public static long getListSize(LinkedMemoryObject mobj) {
+                LinkedMemoryObject tobj = mobj;
+                long size = 0;
+                do {
+                        size += tobj.getSize();
+                        tobj = tobj.getNext();
+                } while (tobj != null && tobj != mobj);
+                return size;
+        }
+
+        /**
+         *  Calculate size of array of linear or circular linked lists.
+         *
+         *  @param mobjs array containting heads of lists
+         *  @return size of all lists
+         */
+        public static long getListsSize(LinkedMemoryObject[] mobjs) {
+                long size = 0;
+                for (int i = 0; i < mobjs.length; ++i) {
+                        LinkedMemoryObject mobj = mobjs[i];
+                        if (mobj != null)
+                                size += getListSize(mobj);
+                }
+                return size;
+        }
+
+        /**
+         *  Create singly linked linear list of objects of fixed size.
+         *
+         *  @param depth length of list
+         *  @param size size of each object
+         *  @return head of created list or null if depth = 0
+         */
+        public static LinkedMemoryObject makeLinearList(int depth, int size) {
+                LinkedMemoryObject mobj = null;
+                for (int i = 0; i < depth; ++i)
+                        mobj = new LinkedMemoryObject(size, mobj);
+                return mobj;
+        }
+
+        /**
+         *  Create singly linked linear list of objects of varying size.
+         *
+         *  @param depth length of list
+         *  @param size maximum size of each object
+         *  @return head of created list or null if depth = 0
+         */
+        public static LinkedMemoryObject makeRandomLinearList(int depth, int size) {
+                if (depth == 0)
+                        return null;
+                LinkedMemoryObject mobj = new LinkedMemoryObject(size);
+                for (int i = 0; i < depth - 1; ++i)
+                        mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);
+                return mobj;
+        }
+
+        /**
+         *  Create singly linked circular linear list of objects of fixed size.
+         *
+         *  @param depth length of list
+         *  @param size size of each object
+         *  @return head of created list or null if depth = 0
+         */
+        public static LinkedMemoryObject makeCircularList(int depth, int size) {
+                if (depth == 0)
+                        return null;
+                LinkedMemoryObject mobj = new LinkedMemoryObject(size);
+                LinkedMemoryObject tmpobj = mobj;
+                for (int i = 1; i < depth; i++)
+                        mobj = new LinkedMemoryObject(size, mobj);
+                tmpobj.setNext(mobj);
+                return tmpobj;
+        }
+
+        /**
+         *  Create singly linked circular linear list of objects of varying size.
+         *
+         *  @param depth length of list
+         *  @param size maximum size of each object
+         *  @return head of created list or null if depth = 0
+         */
+        public static LinkedMemoryObject makeRandomCircularList(int depth, int size) {
+                if (depth == 0)
+                        return null;
+                LinkedMemoryObject mobj = new LinkedMemoryObject(size);
+                LinkedMemoryObject tmpobj = mobj;
+                for (int i = 0; i < depth - 1; i++)
+                        mobj = new LinkedMemoryObject(LocalRandom.nextInt(size), mobj);
+                tmpobj.setNext(mobj);
+                return tmpobj;
+        }
+
+        /**
+         * Create new nonbranchy binary tree.
+         *
+         * Each node in the tree except leaves always has left son. A node
+         * will have right son with probability branchiness.
+         *
+         * @param numberOfNodes number of nodes
+         * @param branchiness branchiness
+         * @param size size of each node
+         * @return root of created tree
+         */
+        public static LinkedMemoryObject makeNonbranchyTree(int numberOfNodes, float branchiness, int size) {
+                LinkedMemoryObject root = null;
+                LinkedMemoryObject current = null;
+                if (numberOfNodes == 0)
+                        return null;
+                else if (numberOfNodes == 1)
+                        return new LinkedMemoryObject(size);
+                else if (numberOfNodes == 2)
+                        return new LinkedMemoryObject(size, makeNonbranchyTree(1, branchiness, size));
+                else {
+                        if (LocalRandom.nextFloat() < branchiness) {
+                                int numberOfLeftNodes = LocalRandom.nextInt(1, numberOfNodes - 1);
+                                int numberOfRightNodes = numberOfNodes - 1 - numberOfLeftNodes;
+                                return new LinkedMemoryObject(
+                                                size,
+                                                makeNonbranchyTree(numberOfLeftNodes, branchiness, size),
+                                                makeNonbranchyTree(numberOfRightNodes, branchiness, size)
+                                                );
+                        } else {
+                                return new LinkedMemoryObject(size, makeNonbranchyTree(numberOfNodes - 1, branchiness, size));
+                        }
+                }
+        }
+
+        /**
+         * Create a balanced tree of given height.
+         *
+         * @param height height of the tree
+         * @param size size of each node
+         * @return created tree
+         */
+        public static Tree makeBalancedTree(int height, long size) {
+                return new Tree(makeBalancedTreeNode(height, size));
+        }
+
+        /**
+         * Get a number of nodes in balanced tree of given height.
+         *
+         * @param heigh height of the tree
+         * @return number of nodes
+         */
+        public static int balancedTreeNodes(int height) {
+                if (height == 0)
+                        return 0;
+                int n = 1;
+                while (height > 1) {
+                        n *= 2;
+                        height--;
+                }
+                return n * 2 - 1;
+        }
+
+        /**
+         * Get approximate memory size occupied by balanced tree
+         * of given height and given node size.
+         *
+         * @param height height of the tree
+         * @param nodeSize size of each node
+         * @return memory size
+         */
+        public static long balancedTreeSize(int height, long nodeSize) {
+                return balancedTreeNodes(height) * nodeSize;
+        }
+
+        /**
+         * Get a height of balanced tree with given number of nodes.
+         *
+         * @param nodes number of nodes
+         * @return height of the tree
+         */
+        public static int balancedTreeHeightFromNodes(int nodes) {
+                if (nodes == 0)
+                        return 0;
+                int h = 1;
+                long n = 1;
+                while (n + n - 1 <= nodes) {
+                        n = n + n;
+                        h = h + 1;
+                }
+                return h - 1;
+        }
+
+        /**
+         * Get approximate height of balanced tree which will occupy
+         * given memory with given node size.
+         *
+         * @param memory memory size
+         * @param nodeSize size of each node
+         * @return approximate height of the tree
+         */
+        public static int balancedTreeHeightFromMemory(long memory, long nodeSize) {
+                return balancedTreeHeightFromNodes((int) (memory / nodeSize));
+        }
+
+        /**
+         * Create balanced tree of given height and node size.
+         *
+         * @param height height of the tree
+         * @param size size of each node
+         * @return root of created tree
+         */
+        public static TreeNode makeBalancedTreeNode(int height, long size) {
+                if (height == 0)
+                        return null;
+                else
+                        return new TreeNode(size, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));
+        }
+
+        /**
+         * Create balanced tree of given height and node size.
+         *
+         * @param height height of the tree
+         * @param size size of each node
+         * @return root of created tree
+         */
+        public static TreeNode makeBalancedTreeNode(int height, long size, GarbageProducer gp) {
+                if (height == 0)
+                        return null;
+                else
+                        return new TreeNode(size, gp, makeBalancedTreeNode(height - 1, size), makeBalancedTreeNode(height - 1, size));
+        }
+
+        /**
+         * Determine if given tree is a balanced tree.
+         *
+         * @param tree tree
+         * @return true if tree is balanced
+         */
+        public static boolean isBalancedTree(TreeNode tree) {
+                return
+                        tree.getActualHeight() == tree.getHeight() &&
+                        tree.getShortestPath() == tree.getHeight();
+        }
+
+        /**
+         *  Fill an array of MemoryObject's with new objects of given size.
+         *
+         *  @param array array
+         *  @param count number of objects to create
+         *  @param size size of each object
+         */
+        public static void fillArray(MemoryObject[] array, int count, int size) {
+                for (int i = 0; i < count; ++i)
+                        array[i] = new MemoryObject(size);
+        }
+
+        /**
+         *  Fill an array of MemoryObject's with new objects of random size.
+         *
+         *  @param array array
+         *  @param count number of objects to create
+         *  @param size maximum size of each object
+         */
+        public static void fillArrayRandom(MemoryObject[] array, int count, int size) {
+                for (int i = 0; i < count; ++i)
+                        array[i] = new MemoryObject(LocalRandom.nextInt(size));
+        }
+
+        /**
+         *  Fill an array of MemoryObject's with new objects of random size.
+         *
+         *  @param array array
+         *  @param count number of objects to create
+         *  @param size maximum size of each object
+         */
+        public static void fillArrayRandom(LinkedMemoryObject[] array, int count, int size) {
+                for (int i = 0; i < count; ++i)
+                        array[i] = new LinkedMemoryObject(LocalRandom.nextInt(size));
+        }
+
+        public static void dumpStatistics(PrintStream out) {
+                out.println(Runtime.getRuntime().freeMemory());
+                out.flush();
+        }
+
+        public static void dumpStatistics(Log log) {
+                log.info(Runtime.getRuntime().freeMemory());
+        }
+
+        public static void dumpStatistics() {
+                dumpStatistics(System.out);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/MemoryObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+/**
+ *  An object that occupies approximately given number of bytes in memory.
+ */
+public class MemoryObject {
+        private static int diff = (int) Memory.getObjectExtraSize();
+        private byte storage[];
+
+        /**
+         *  Create an object that occupies given number of bytes.
+         *
+         *  @param size size
+         */
+        public MemoryObject(int size) {
+                if (size > diff)
+                        storage = new byte[size - diff];
+        }
+
+        public final byte[] getStorage() {
+                return storage;
+        }
+
+        public final int getSize() {
+                return storage.length;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/NonbranchyTree.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import java.io.*;
+import java.util.*;
+
+import nsk.share.test.ExecutionController;
+
+/**
+ * <tt>NonbranchyTree</tt> defines a tree structure. Each node of the tree
+ * always has one son. A node may have the second son with probability
+ * <tt>branchiness</tt>.
+ */
+public class NonbranchyTree {
+
+    /** Minimal size of each node (in bytes) */
+    public final static int MIN_NODE_SIZE = 20;
+    private Node root;
+    private Random random;
+    private int numberOfNodes;
+    private float branchiness;
+    private int size;
+    private ExecutionController controller;
+
+    /**
+     * Creates a new tree with number of nodes not more than
+     * <tt>numberOfNodes</tt>. The implementation uses recursion to build the
+     * tree, so if <tt>StackOverflowError</tt> or <tt>OutOfMemoryError</tt> is
+     * thrown, the recursion is stopped and the method finishes building of the
+     * tree. Each node consists of <tt>byte[]</tt> of length <tt>size</tt>.
+     *
+     * @param numberOfNodes maximum number of nodes for the tree.
+     * @param branchiness probability for each node to have the second son.
+     * @param size number of bytes to store in a node.
+     *
+     * @throws <i>IllegalArgumentException</i> if <tt>numberOfNodes</tt> is
+     *         less than 1; or <tt>branchiness</tt> is greater than 1, or less
+     *         or equal than 0; or <tt>size</tt> is less than 1.
+     *
+     */
+    public NonbranchyTree(int numberOfNodes, float branchiness, int size) {
+        this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), null);
+        initTree();
+    }
+
+    public NonbranchyTree(int numberOfNodes, float branchiness, int size, ExecutionController controller) {
+        this(numberOfNodes, branchiness, size, new Random(System.currentTimeMillis()), controller);
+        initTree();
+    }
+
+    private NonbranchyTree(int numberOfNodes, float branchiness, int size, Random random, ExecutionController controller) {
+        this.numberOfNodes = numberOfNodes;
+        this.branchiness = branchiness;
+        this.size = size;
+        this.random = random;
+        this.controller = controller;
+    }
+
+    private void initTree() {
+        if (numberOfNodes < 1) {
+            throw new IllegalArgumentException("Illegal number of nodes: "
+                                             + numberOfNodes + ", must be at "
+                                             + "least 1.");
+        }
+        if ( (branchiness >= 1) || (branchiness <= 0) ) {
+            throw new IllegalArgumentException("Illegal value of branchiness: "
+                                             + numberOfNodes + ", must be at "
+                                             + "greater than 0 and less than "
+                                             + " 1.");
+        }
+        if (size < 1) {
+            throw new IllegalArgumentException("Illegal size of nodes: "
+                                             + size + ", must be at least 1.");
+        }
+        root = createTree(numberOfNodes, size);
+    }
+
+    // Create a new tree with specified number of nodes and size of each node
+    private Node createTree(int numberOfNodes, int size) {
+        // Make sure we respect the controller and stop test after
+        // given time.
+        if (controller != null && !controller.continueExecution()) {
+            return null;
+        }
+
+        Node node = new Node(size);
+        try {
+            if (numberOfNodes == 0) {
+                // No more nodes need to be built
+                return null;
+            } else if (numberOfNodes == 1) {
+                return node;
+            } else if (numberOfNodes == 2) {
+                node.left = createTree(1, size);
+                return node;
+            } else {
+                // Create a few nodes
+                if (makeRightNode()) {
+                    // The node will have two sons
+                    int leftNodes = 1 + random.nextInt(numberOfNodes - 2);
+                    int rightNodes = numberOfNodes - 1 - leftNodes;
+
+                    node.left = createTree(leftNodes, size);
+                    node.right = createTree(rightNodes, size);
+                } else {
+                    // The node will have just one son
+                    Node leftTree = createTree(numberOfNodes - 1, size);
+                    node.left = leftTree;
+                }
+                return node;
+            } // if
+        } catch(StackOverflowError e) {
+            // No more memory for such long tree
+            return node;
+        } catch(OutOfMemoryError e) {
+            // No more memory for such long tree
+            return node;
+        } // try
+    } // createTree()
+
+    // Define the "branchiness" of the tree
+    private boolean makeRightNode() {
+        return (random.nextFloat() < branchiness);
+    }
+
+    /**
+     * Bends the tree. A son of a leaf of the tree is set to the root node.
+     *
+     */
+    public void bend() {
+        bend(root);
+    }
+
+    // Bend the tree: make a reference from a leat of the tree to the specified
+    // node
+    private void bend(Node markedNode) {
+        Node node = root;
+
+        while ( (node.left != null) || (node.right != null) )
+            node = node.left;
+        node.right = markedNode;
+    }
+
+    /**
+     * Prints the whole tree from the root to the defined PrintStream.
+     *
+     * @param out PrintStream to print the tree in
+     *
+     */
+    public void print(PrintStream out) {
+        print(out, root);
+    }
+
+    // Print the sub-tree from the specified node and down
+    private void print(PrintStream out, Node node) {
+        node.print(out);
+        if (node.left != null)
+            print(out, node.left);
+        if (node.right != null)
+            print(out, node.right);
+    }
+}
+
+// The class defines a node of a tree
+class Node {
+    Node left;
+    Node right;
+    byte[] core;
+
+    Node(int size) {
+        left = null;
+        right = null;
+        core = new byte[size];
+
+        // Initizlize the core array
+        for (int i = 0; i < size; i++)
+            core[i] = (byte) i;
+    }
+
+    // Print the node info
+    void print(PrintStream out) {
+        out.println("node = " + this + " (" + left + ", " + right + ")");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/OOMStress.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+/**
+ * Marker interface to tell that a something stresses OOM.
+ */
+public interface OOMStress {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/ThreadedGCTest.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc;
+
+import nsk.share.runner.*;
+import nsk.share.test.ExecutionController;
+import nsk.share.Consts;
+
+/**
+ * Test that executes a number of tasks.
+ *
+ * How these tasks are used is determined by MultiRunner.
+ * Usually they are executed in separate threads in cycle
+ * for some time or for some iterations.
+ *
+ * @see nsk.share.runner.MultiRunner
+ * @see nsk.share.runner.ThreadsRunner
+ */
+public abstract class ThreadedGCTest extends GCTestBase implements MultiRunnerAware {
+        private MultiRunner runner;
+
+        /**
+         * Create a task with index i.
+         *
+         * Subclasses should to override this method
+         * to created neccessary tasks.
+         *
+         * @param i index of task
+         * @return task to run or null
+         */
+        protected abstract Runnable createRunnable(int i);
+
+        protected ExecutionController getExecutionController() {
+                return runner.getExecutionController();
+        }
+
+        protected final boolean runThreads() {
+                for (int i = 0; i < runParams.getNumberOfThreads(); ++i) {
+                        Runnable runnable = createRunnable(i);
+                        if (runnable != null)
+                                runner.add(runnable);
+                }
+                runner.run();
+                return runner.isSuccessful();
+        }
+
+        public void run() {
+                if (!runThreads())
+                        setFailed(true);
+        }
+
+        public final void setRunner(MultiRunner runner) {
+                this.runner = runner;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/TwoFieldsObject.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.gc;
+
+/**
+ * An object with two fields of same type.
+ */
+public class TwoFieldsObject<T> {
+        private T left, right;
+
+        public TwoFieldsObject(T left, T right) {
+                setLeft(left);
+                setRight(right);
+        }
+
+        public final void setLeft(T left) {
+                this.left = left;
+        }
+
+        public final void setRight(T right) {
+                this.right = right;
+        }
+
+        public final T getLeft() {
+                return left;
+        }
+
+        public final T getRight() {
+                return right;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/classes/Classes.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,5024 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.classes;
+
+class Class1 {
+        public Class1(){
+
+        }
+}
+class Class2 {
+        public Class2(){
+
+        }
+}
+class Class3 {
+        public Class3(){
+
+        }
+}
+class Class4 {
+        public Class4(){
+
+        }
+}
+class Class5 {
+        public Class5(){
+
+        }
+}
+class Class6 {
+        public Class6(){
+
+        }
+}
+class Class7 {
+        public Class7(){
+
+        }
+}
+class Class8 {
+        public Class8(){
+
+        }
+}
+class Class9 {
+        public Class9(){
+
+        }
+}
+class Class10 {
+        public Class10(){
+
+        }
+}
+class Class11 {
+        public Class11(){
+
+        }
+}
+class Class12 {
+        public Class12(){
+
+        }
+}
+class Class13 {
+        public Class13(){
+
+        }
+}
+class Class14 {
+        public Class14(){
+
+        }
+}
+class Class15 {
+        public Class15(){
+
+        }
+}
+class Class16 {
+        public Class16(){
+
+        }
+}
+class Class17 {
+        public Class17(){
+
+        }
+}
+class Class18 {
+        public Class18(){
+
+        }
+}
+class Class19 {
+        public Class19(){
+
+        }
+}
+class Class20 {
+        public Class20(){
+
+        }
+}
+class Class21 {
+        public Class21(){
+
+        }
+}
+class Class22 {
+        public Class22(){
+
+        }
+}
+class Class23 {
+        public Class23(){
+
+        }
+}
+class Class24 {
+        public Class24(){
+
+        }
+}
+class Class25 {
+        public Class25(){
+
+        }
+}
+class Class26 {
+        public Class26(){
+
+        }
+}
+class Class27 {
+        public Class27(){
+
+        }
+}
+class Class28 {
+        public Class28(){
+
+        }
+}
+class Class29 {
+        public Class29(){
+
+        }
+}
+class Class30 {
+        public Class30(){
+
+        }
+}
+class Class31 {
+        public Class31(){
+
+        }
+}
+class Class32 {
+        public Class32(){
+
+        }
+}
+class Class33 {
+        public Class33(){
+
+        }
+}
+class Class34 {
+        public Class34(){
+
+        }
+}
+class Class35 {
+        public Class35(){
+
+        }
+}
+class Class36 {
+        public Class36(){
+
+        }
+}
+class Class37 {
+        public Class37(){
+
+        }
+}
+class Class38 {
+        public Class38(){
+
+        }
+}
+class Class39 {
+        public Class39(){
+
+        }
+}
+class Class40 {
+        public Class40(){
+
+        }
+}
+class Class41 {
+        public Class41(){
+
+        }
+}
+class Class42 {
+        public Class42(){
+
+        }
+}
+class Class43 {
+        public Class43(){
+
+        }
+}
+class Class44 {
+        public Class44(){
+
+        }
+}
+class Class45 {
+        public Class45(){
+
+        }
+}
+class Class46 {
+        public Class46(){
+
+        }
+}
+class Class47 {
+        public Class47(){
+
+        }
+}
+class Class48 {
+        public Class48(){
+
+        }
+}
+class Class49 {
+        public Class49(){
+
+        }
+}
+class Class50 {
+        public Class50(){
+
+        }
+}
+class Class51 {
+        public Class51(){
+
+        }
+}
+class Class52 {
+        public Class52(){
+
+        }
+}
+class Class53 {
+        public Class53(){
+
+        }
+}
+class Class54 {
+        public Class54(){
+
+        }
+}
+class Class55 {
+        public Class55(){
+
+        }
+}
+class Class56 {
+        public Class56(){
+
+        }
+}
+class Class57 {
+        public Class57(){
+
+        }
+}
+class Class58 {
+        public Class58(){
+
+        }
+}
+class Class59 {
+        public Class59(){
+
+        }
+}
+class Class60 {
+        public Class60(){
+
+        }
+}
+class Class61 {
+        public Class61(){
+
+        }
+}
+class Class62 {
+        public Class62(){
+
+        }
+}
+class Class63 {
+        public Class63(){
+
+        }
+}
+class Class64 {
+        public Class64(){
+
+        }
+}
+class Class65 {
+        public Class65(){
+
+        }
+}
+class Class66 {
+        public Class66(){
+
+        }
+}
+class Class67 {
+        public Class67(){
+
+        }
+}
+class Class68 {
+        public Class68(){
+
+        }
+}
+class Class69 {
+        public Class69(){
+
+        }
+}
+class Class70 {
+        public Class70(){
+
+        }
+}
+class Class71 {
+        public Class71(){
+
+        }
+}
+class Class72 {
+        public Class72(){
+
+        }
+}
+class Class73 {
+        public Class73(){
+
+        }
+}
+class Class74 {
+        public Class74(){
+
+        }
+}
+class Class75 {
+        public Class75(){
+
+        }
+}
+class Class76 {
+        public Class76(){
+
+        }
+}
+class Class77 {
+        public Class77(){
+
+        }
+}
+class Class78 {
+        public Class78(){
+
+        }
+}
+class Class79 {
+        public Class79(){
+
+        }
+}
+class Class80 {
+        public Class80(){
+
+        }
+}
+class Class81 {
+        public Class81(){
+
+        }
+}
+class Class82 {
+        public Class82(){
+
+        }
+}
+class Class83 {
+        public Class83(){
+
+        }
+}
+class Class84 {
+        public Class84(){
+
+        }
+}
+class Class85 {
+        public Class85(){
+
+        }
+}
+class Class86 {
+        public Class86(){
+
+        }
+}
+class Class87 {
+        public Class87(){
+
+        }
+}
+class Class88 {
+        public Class88(){
+
+        }
+}
+class Class89 {
+        public Class89(){
+
+        }
+}
+class Class90 {
+        public Class90(){
+
+        }
+}
+class Class91 {
+        public Class91(){
+
+        }
+}
+class Class92 {
+        public Class92(){
+
+        }
+}
+class Class93 {
+        public Class93(){
+
+        }
+}
+class Class94 {
+        public Class94(){
+
+        }
+}
+class Class95 {
+        public Class95(){
+
+        }
+}
+class Class96 {
+        public Class96(){
+
+        }
+}
+class Class97 {
+        public Class97(){
+
+        }
+}
+class Class98 {
+        public Class98(){
+
+        }
+}
+class Class99 {
+        public Class99(){
+
+        }
+}
+class Class100 {
+        public Class100(){
+
+        }
+}
+class Class101 {
+        public Class101(){
+
+        }
+}
+class Class102 {
+        public Class102(){
+
+        }
+}
+class Class103 {
+        public Class103(){
+
+        }
+}
+class Class104 {
+        public Class104(){
+
+        }
+}
+class Class105 {
+        public Class105(){
+
+        }
+}
+class Class106 {
+        public Class106(){
+
+        }
+}
+class Class107 {
+        public Class107(){
+
+        }
+}
+class Class108 {
+        public Class108(){
+
+        }
+}
+class Class109 {
+        public Class109(){
+
+        }
+}
+class Class110 {
+        public Class110(){
+
+        }
+}
+class Class111 {
+        public Class111(){
+
+        }
+}
+class Class112 {
+        public Class112(){
+
+        }
+}
+class Class113 {
+        public Class113(){
+
+        }
+}
+class Class114 {
+        public Class114(){
+
+        }
+}
+class Class115 {
+        public Class115(){
+
+        }
+}
+class Class116 {
+        public Class116(){
+
+        }
+}
+class Class117 {
+        public Class117(){
+
+        }
+}
+class Class118 {
+        public Class118(){
+
+        }
+}
+class Class119 {
+        public Class119(){
+
+        }
+}
+class Class120 {
+        public Class120(){
+
+        }
+}
+class Class121 {
+        public Class121(){
+
+        }
+}
+class Class122 {
+        public Class122(){
+
+        }
+}
+class Class123 {
+        public Class123(){
+
+        }
+}
+class Class124 {
+        public Class124(){
+
+        }
+}
+class Class125 {
+        public Class125(){
+
+        }
+}
+class Class126 {
+        public Class126(){
+
+        }
+}
+class Class127 {
+        public Class127(){
+
+        }
+}
+class Class128 {
+        public Class128(){
+
+        }
+}
+class Class129 {
+        public Class129(){
+
+        }
+}
+class Class130 {
+        public Class130(){
+
+        }
+}
+class Class131 {
+        public Class131(){
+
+        }
+}
+class Class132 {
+        public Class132(){
+
+        }
+}
+class Class133 {
+        public Class133(){
+
+        }
+}
+class Class134 {
+        public Class134(){
+
+        }
+}
+class Class135 {
+        public Class135(){
+
+        }
+}
+class Class136 {
+        public Class136(){
+
+        }
+}
+class Class137 {
+        public Class137(){
+
+        }
+}
+class Class138 {
+        public Class138(){
+
+        }
+}
+class Class139 {
+        public Class139(){
+
+        }
+}
+class Class140 {
+        public Class140(){
+
+        }
+}
+class Class141 {
+        public Class141(){
+
+        }
+}
+class Class142 {
+        public Class142(){
+
+        }
+}
+class Class143 {
+        public Class143(){
+
+        }
+}
+class Class144 {
+        public Class144(){
+
+        }
+}
+class Class145 {
+        public Class145(){
+
+        }
+}
+class Class146 {
+        public Class146(){
+
+        }
+}
+class Class147 {
+        public Class147(){
+
+        }
+}
+class Class148 {
+        public Class148(){
+
+        }
+}
+class Class149 {
+        public Class149(){
+
+        }
+}
+class Class150 {
+        public Class150(){
+
+        }
+}
+class Class151 {
+        public Class151(){
+
+        }
+}
+class Class152 {
+        public Class152(){
+
+        }
+}
+class Class153 {
+        public Class153(){
+
+        }
+}
+class Class154 {
+        public Class154(){
+
+        }
+}
+class Class155 {
+        public Class155(){
+
+        }
+}
+class Class156 {
+        public Class156(){
+
+        }
+}
+class Class157 {
+        public Class157(){
+
+        }
+}
+class Class158 {
+        public Class158(){
+
+        }
+}
+class Class159 {
+        public Class159(){
+
+        }
+}
+class Class160 {
+        public Class160(){
+
+        }
+}
+class Class161 {
+        public Class161(){
+
+        }
+}
+class Class162 {
+        public Class162(){
+
+        }
+}
+class Class163 {
+        public Class163(){
+
+        }
+}
+class Class164 {
+        public Class164(){
+
+        }
+}
+class Class165 {
+        public Class165(){
+
+        }
+}
+class Class166 {
+        public Class166(){
+
+        }
+}
+class Class167 {
+        public Class167(){
+
+        }
+}
+class Class168 {
+        public Class168(){
+
+        }
+}
+class Class169 {
+        public Class169(){
+
+        }
+}
+class Class170 {
+        public Class170(){
+
+        }
+}
+class Class171 {
+        public Class171(){
+
+        }
+}
+class Class172 {
+        public Class172(){
+
+        }
+}
+class Class173 {
+        public Class173(){
+
+        }
+}
+class Class174 {
+        public Class174(){
+
+        }
+}
+class Class175 {
+        public Class175(){
+
+        }
+}
+class Class176 {
+        public Class176(){
+
+        }
+}
+class Class177 {
+        public Class177(){
+
+        }
+}
+class Class178 {
+        public Class178(){
+
+        }
+}
+class Class179 {
+        public Class179(){
+
+        }
+}
+class Class180 {
+        public Class180(){
+
+        }
+}
+class Class181 {
+        public Class181(){
+
+        }
+}
+class Class182 {
+        public Class182(){
+
+        }
+}
+class Class183 {
+        public Class183(){
+
+        }
+}
+class Class184 {
+        public Class184(){
+
+        }
+}
+class Class185 {
+        public Class185(){
+
+        }
+}
+class Class186 {
+        public Class186(){
+
+        }
+}
+class Class187 {
+        public Class187(){
+
+        }
+}
+class Class188 {
+        public Class188(){
+
+        }
+}
+class Class189 {
+        public Class189(){
+
+        }
+}
+class Class190 {
+        public Class190(){
+
+        }
+}
+class Class191 {
+        public Class191(){
+
+        }
+}
+class Class192 {
+        public Class192(){
+
+        }
+}
+class Class193 {
+        public Class193(){
+
+        }
+}
+class Class194 {
+        public Class194(){
+
+        }
+}
+class Class195 {
+        public Class195(){
+
+        }
+}
+class Class196 {
+        public Class196(){
+
+        }
+}
+class Class197 {
+        public Class197(){
+
+        }
+}
+class Class198 {
+        public Class198(){
+
+        }
+}
+class Class199 {
+        public Class199(){
+
+        }
+}
+class Class200 {
+        public Class200(){
+
+        }
+}
+class Class201 {
+        public Class201(){
+
+        }
+}
+class Class202 {
+        public Class202(){
+
+        }
+}
+class Class203 {
+        public Class203(){
+
+        }
+}
+class Class204 {
+        public Class204(){
+
+        }
+}
+class Class205 {
+        public Class205(){
+
+        }
+}
+class Class206 {
+        public Class206(){
+
+        }
+}
+class Class207 {
+        public Class207(){
+
+        }
+}
+class Class208 {
+        public Class208(){
+
+        }
+}
+class Class209 {
+        public Class209(){
+
+        }
+}
+class Class210 {
+        public Class210(){
+
+        }
+}
+class Class211 {
+        public Class211(){
+
+        }
+}
+class Class212 {
+        public Class212(){
+
+        }
+}
+class Class213 {
+        public Class213(){
+
+        }
+}
+class Class214 {
+        public Class214(){
+
+        }
+}
+class Class215 {
+        public Class215(){
+
+        }
+}
+class Class216 {
+        public Class216(){
+
+        }
+}
+class Class217 {
+        public Class217(){
+
+        }
+}
+class Class218 {
+        public Class218(){
+
+        }
+}
+class Class219 {
+        public Class219(){
+
+        }
+}
+class Class220 {
+        public Class220(){
+
+        }
+}
+class Class221 {
+        public Class221(){
+
+        }
+}
+class Class222 {
+        public Class222(){
+
+        }
+}
+class Class223 {
+        public Class223(){
+
+        }
+}
+class Class224 {
+        public Class224(){
+
+        }
+}
+class Class225 {
+        public Class225(){
+
+        }
+}
+class Class226 {
+        public Class226(){
+
+        }
+}
+class Class227 {
+        public Class227(){
+
+        }
+}
+class Class228 {
+        public Class228(){
+
+        }
+}
+class Class229 {
+        public Class229(){
+
+        }
+}
+class Class230 {
+        public Class230(){
+
+        }
+}
+class Class231 {
+        public Class231(){
+
+        }
+}
+class Class232 {
+        public Class232(){
+
+        }
+}
+class Class233 {
+        public Class233(){
+
+        }
+}
+class Class234 {
+        public Class234(){
+
+        }
+}
+class Class235 {
+        public Class235(){
+
+        }
+}
+class Class236 {
+        public Class236(){
+
+        }
+}
+class Class237 {
+        public Class237(){
+
+        }
+}
+class Class238 {
+        public Class238(){
+
+        }
+}
+class Class239 {
+        public Class239(){
+
+        }
+}
+class Class240 {
+        public Class240(){
+
+        }
+}
+class Class241 {
+        public Class241(){
+
+        }
+}
+class Class242 {
+        public Class242(){
+
+        }
+}
+class Class243 {
+        public Class243(){
+
+        }
+}
+class Class244 {
+        public Class244(){
+
+        }
+}
+class Class245 {
+        public Class245(){
+
+        }
+}
+class Class246 {
+        public Class246(){
+
+        }
+}
+class Class247 {
+        public Class247(){
+
+        }
+}
+class Class248 {
+        public Class248(){
+
+        }
+}
+class Class249 {
+        public Class249(){
+
+        }
+}
+class Class250 {
+        public Class250(){
+
+        }
+}
+class Class251 {
+        public Class251(){
+
+        }
+}
+class Class252 {
+        public Class252(){
+
+        }
+}
+class Class253 {
+        public Class253(){
+
+        }
+}
+class Class254 {
+        public Class254(){
+
+        }
+}
+class Class255 {
+        public Class255(){
+
+        }
+}
+class Class256 {
+        public Class256(){
+
+        }
+}
+class Class257 {
+        public Class257(){
+
+        }
+}
+class Class258 {
+        public Class258(){
+
+        }
+}
+class Class259 {
+        public Class259(){
+
+        }
+}
+class Class260 {
+        public Class260(){
+
+        }
+}
+class Class261 {
+        public Class261(){
+
+        }
+}
+class Class262 {
+        public Class262(){
+
+        }
+}
+class Class263 {
+        public Class263(){
+
+        }
+}
+class Class264 {
+        public Class264(){
+
+        }
+}
+class Class265 {
+        public Class265(){
+
+        }
+}
+class Class266 {
+        public Class266(){
+
+        }
+}
+class Class267 {
+        public Class267(){
+
+        }
+}
+class Class268 {
+        public Class268(){
+
+        }
+}
+class Class269 {
+        public Class269(){
+
+        }
+}
+class Class270 {
+        public Class270(){
+
+        }
+}
+class Class271 {
+        public Class271(){
+
+        }
+}
+class Class272 {
+        public Class272(){
+
+        }
+}
+class Class273 {
+        public Class273(){
+
+        }
+}
+class Class274 {
+        public Class274(){
+
+        }
+}
+class Class275 {
+        public Class275(){
+
+        }
+}
+class Class276 {
+        public Class276(){
+
+        }
+}
+class Class277 {
+        public Class277(){
+
+        }
+}
+class Class278 {
+        public Class278(){
+
+        }
+}
+class Class279 {
+        public Class279(){
+
+        }
+}
+class Class280 {
+        public Class280(){
+
+        }
+}
+class Class281 {
+        public Class281(){
+
+        }
+}
+class Class282 {
+        public Class282(){
+
+        }
+}
+class Class283 {
+        public Class283(){
+
+        }
+}
+class Class284 {
+        public Class284(){
+
+        }
+}
+class Class285 {
+        public Class285(){
+
+        }
+}
+class Class286 {
+        public Class286(){
+
+        }
+}
+class Class287 {
+        public Class287(){
+
+        }
+}
+class Class288 {
+        public Class288(){
+
+        }
+}
+class Class289 {
+        public Class289(){
+
+        }
+}
+class Class290 {
+        public Class290(){
+
+        }
+}
+class Class291 {
+        public Class291(){
+
+        }
+}
+class Class292 {
+        public Class292(){
+
+        }
+}
+class Class293 {
+        public Class293(){
+
+        }
+}
+class Class294 {
+        public Class294(){
+
+        }
+}
+class Class295 {
+        public Class295(){
+
+        }
+}
+class Class296 {
+        public Class296(){
+
+        }
+}
+class Class297 {
+        public Class297(){
+
+        }
+}
+class Class298 {
+        public Class298(){
+
+        }
+}
+class Class299 {
+        public Class299(){
+
+        }
+}
+class Class300 {
+        public Class300(){
+
+        }
+}
+class Class301 {
+        public Class301(){
+
+        }
+}
+class Class302 {
+        public Class302(){
+
+        }
+}
+class Class303 {
+        public Class303(){
+
+        }
+}
+class Class304 {
+        public Class304(){
+
+        }
+}
+class Class305 {
+        public Class305(){
+
+        }
+}
+class Class306 {
+        public Class306(){
+
+        }
+}
+class Class307 {
+        public Class307(){
+
+        }
+}
+class Class308 {
+        public Class308(){
+
+        }
+}
+class Class309 {
+        public Class309(){
+
+        }
+}
+class Class310 {
+        public Class310(){
+
+        }
+}
+class Class311 {
+        public Class311(){
+
+        }
+}
+class Class312 {
+        public Class312(){
+
+        }
+}
+class Class313 {
+        public Class313(){
+
+        }
+}
+class Class314 {
+        public Class314(){
+
+        }
+}
+class Class315 {
+        public Class315(){
+
+        }
+}
+class Class316 {
+        public Class316(){
+
+        }
+}
+class Class317 {
+        public Class317(){
+
+        }
+}
+class Class318 {
+        public Class318(){
+
+        }
+}
+class Class319 {
+        public Class319(){
+
+        }
+}
+class Class320 {
+        public Class320(){
+
+        }
+}
+class Class321 {
+        public Class321(){
+
+        }
+}
+class Class322 {
+        public Class322(){
+
+        }
+}
+class Class323 {
+        public Class323(){
+
+        }
+}
+class Class324 {
+        public Class324(){
+
+        }
+}
+class Class325 {
+        public Class325(){
+
+        }
+}
+class Class326 {
+        public Class326(){
+
+        }
+}
+class Class327 {
+        public Class327(){
+
+        }
+}
+class Class328 {
+        public Class328(){
+
+        }
+}
+class Class329 {
+        public Class329(){
+
+        }
+}
+class Class330 {
+        public Class330(){
+
+        }
+}
+class Class331 {
+        public Class331(){
+
+        }
+}
+class Class332 {
+        public Class332(){
+
+        }
+}
+class Class333 {
+        public Class333(){
+
+        }
+}
+class Class334 {
+        public Class334(){
+
+        }
+}
+class Class335 {
+        public Class335(){
+
+        }
+}
+class Class336 {
+        public Class336(){
+
+        }
+}
+class Class337 {
+        public Class337(){
+
+        }
+}
+class Class338 {
+        public Class338(){
+
+        }
+}
+class Class339 {
+        public Class339(){
+
+        }
+}
+class Class340 {
+        public Class340(){
+
+        }
+}
+class Class341 {
+        public Class341(){
+
+        }
+}
+class Class342 {
+        public Class342(){
+
+        }
+}
+class Class343 {
+        public Class343(){
+
+        }
+}
+class Class344 {
+        public Class344(){
+
+        }
+}
+class Class345 {
+        public Class345(){
+
+        }
+}
+class Class346 {
+        public Class346(){
+
+        }
+}
+class Class347 {
+        public Class347(){
+
+        }
+}
+class Class348 {
+        public Class348(){
+
+        }
+}
+class Class349 {
+        public Class349(){
+
+        }
+}
+class Class350 {
+        public Class350(){
+
+        }
+}
+class Class351 {
+        public Class351(){
+
+        }
+}
+class Class352 {
+        public Class352(){
+
+        }
+}
+class Class353 {
+        public Class353(){
+
+        }
+}
+class Class354 {
+        public Class354(){
+
+        }
+}
+class Class355 {
+        public Class355(){
+
+        }
+}
+class Class356 {
+        public Class356(){
+
+        }
+}
+class Class357 {
+        public Class357(){
+
+        }
+}
+class Class358 {
+        public Class358(){
+
+        }
+}
+class Class359 {
+        public Class359(){
+
+        }
+}
+class Class360 {
+        public Class360(){
+
+        }
+}
+class Class361 {
+        public Class361(){
+
+        }
+}
+class Class362 {
+        public Class362(){
+
+        }
+}
+class Class363 {
+        public Class363(){
+
+        }
+}
+class Class364 {
+        public Class364(){
+
+        }
+}
+class Class365 {
+        public Class365(){
+
+        }
+}
+class Class366 {
+        public Class366(){
+
+        }
+}
+class Class367 {
+        public Class367(){
+
+        }
+}
+class Class368 {
+        public Class368(){
+
+        }
+}
+class Class369 {
+        public Class369(){
+
+        }
+}
+class Class370 {
+        public Class370(){
+
+        }
+}
+class Class371 {
+        public Class371(){
+
+        }
+}
+class Class372 {
+        public Class372(){
+
+        }
+}
+class Class373 {
+        public Class373(){
+
+        }
+}
+class Class374 {
+        public Class374(){
+
+        }
+}
+class Class375 {
+        public Class375(){
+
+        }
+}
+class Class376 {
+        public Class376(){
+
+        }
+}
+class Class377 {
+        public Class377(){
+
+        }
+}
+class Class378 {
+        public Class378(){
+
+        }
+}
+class Class379 {
+        public Class379(){
+
+        }
+}
+class Class380 {
+        public Class380(){
+
+        }
+}
+class Class381 {
+        public Class381(){
+
+        }
+}
+class Class382 {
+        public Class382(){
+
+        }
+}
+class Class383 {
+        public Class383(){
+
+        }
+}
+class Class384 {
+        public Class384(){
+
+        }
+}
+class Class385 {
+        public Class385(){
+
+        }
+}
+class Class386 {
+        public Class386(){
+
+        }
+}
+class Class387 {
+        public Class387(){
+
+        }
+}
+class Class388 {
+        public Class388(){
+
+        }
+}
+class Class389 {
+        public Class389(){
+
+        }
+}
+class Class390 {
+        public Class390(){
+
+        }
+}
+class Class391 {
+        public Class391(){
+
+        }
+}
+class Class392 {
+        public Class392(){
+
+        }
+}
+class Class393 {
+        public Class393(){
+
+        }
+}
+class Class394 {
+        public Class394(){
+
+        }
+}
+class Class395 {
+        public Class395(){
+
+        }
+}
+class Class396 {
+        public Class396(){
+
+        }
+}
+class Class397 {
+        public Class397(){
+
+        }
+}
+class Class398 {
+        public Class398(){
+
+        }
+}
+class Class399 {
+        public Class399(){
+
+        }
+}
+class Class400 {
+        public Class400(){
+
+        }
+}
+class Class401 {
+        public Class401(){
+
+        }
+}
+class Class402 {
+        public Class402(){
+
+        }
+}
+class Class403 {
+        public Class403(){
+
+        }
+}
+class Class404 {
+        public Class404(){
+
+        }
+}
+class Class405 {
+        public Class405(){
+
+        }
+}
+class Class406 {
+        public Class406(){
+
+        }
+}
+class Class407 {
+        public Class407(){
+
+        }
+}
+class Class408 {
+        public Class408(){
+
+        }
+}
+class Class409 {
+        public Class409(){
+
+        }
+}
+class Class410 {
+        public Class410(){
+
+        }
+}
+class Class411 {
+        public Class411(){
+
+        }
+}
+class Class412 {
+        public Class412(){
+
+        }
+}
+class Class413 {
+        public Class413(){
+
+        }
+}
+class Class414 {
+        public Class414(){
+
+        }
+}
+class Class415 {
+        public Class415(){
+
+        }
+}
+class Class416 {
+        public Class416(){
+
+        }
+}
+class Class417 {
+        public Class417(){
+
+        }
+}
+class Class418 {
+        public Class418(){
+
+        }
+}
+class Class419 {
+        public Class419(){
+
+        }
+}
+class Class420 {
+        public Class420(){
+
+        }
+}
+class Class421 {
+        public Class421(){
+
+        }
+}
+class Class422 {
+        public Class422(){
+
+        }
+}
+class Class423 {
+        public Class423(){
+
+        }
+}
+class Class424 {
+        public Class424(){
+
+        }
+}
+class Class425 {
+        public Class425(){
+
+        }
+}
+class Class426 {
+        public Class426(){
+
+        }
+}
+class Class427 {
+        public Class427(){
+
+        }
+}
+class Class428 {
+        public Class428(){
+
+        }
+}
+class Class429 {
+        public Class429(){
+
+        }
+}
+class Class430 {
+        public Class430(){
+
+        }
+}
+class Class431 {
+        public Class431(){
+
+        }
+}
+class Class432 {
+        public Class432(){
+
+        }
+}
+class Class433 {
+        public Class433(){
+
+        }
+}
+class Class434 {
+        public Class434(){
+
+        }
+}
+class Class435 {
+        public Class435(){
+
+        }
+}
+class Class436 {
+        public Class436(){
+
+        }
+}
+class Class437 {
+        public Class437(){
+
+        }
+}
+class Class438 {
+        public Class438(){
+
+        }
+}
+class Class439 {
+        public Class439(){
+
+        }
+}
+class Class440 {
+        public Class440(){
+
+        }
+}
+class Class441 {
+        public Class441(){
+
+        }
+}
+class Class442 {
+        public Class442(){
+
+        }
+}
+class Class443 {
+        public Class443(){
+
+        }
+}
+class Class444 {
+        public Class444(){
+
+        }
+}
+class Class445 {
+        public Class445(){
+
+        }
+}
+class Class446 {
+        public Class446(){
+
+        }
+}
+class Class447 {
+        public Class447(){
+
+        }
+}
+class Class448 {
+        public Class448(){
+
+        }
+}
+class Class449 {
+        public Class449(){
+
+        }
+}
+class Class450 {
+        public Class450(){
+
+        }
+}
+class Class451 {
+        public Class451(){
+
+        }
+}
+class Class452 {
+        public Class452(){
+
+        }
+}
+class Class453 {
+        public Class453(){
+
+        }
+}
+class Class454 {
+        public Class454(){
+
+        }
+}
+class Class455 {
+        public Class455(){
+
+        }
+}
+class Class456 {
+        public Class456(){
+
+        }
+}
+class Class457 {
+        public Class457(){
+
+        }
+}
+class Class458 {
+        public Class458(){
+
+        }
+}
+class Class459 {
+        public Class459(){
+
+        }
+}
+class Class460 {
+        public Class460(){
+
+        }
+}
+class Class461 {
+        public Class461(){
+
+        }
+}
+class Class462 {
+        public Class462(){
+
+        }
+}
+class Class463 {
+        public Class463(){
+
+        }
+}
+class Class464 {
+        public Class464(){
+
+        }
+}
+class Class465 {
+        public Class465(){
+
+        }
+}
+class Class466 {
+        public Class466(){
+
+        }
+}
+class Class467 {
+        public Class467(){
+
+        }
+}
+class Class468 {
+        public Class468(){
+
+        }
+}
+class Class469 {
+        public Class469(){
+
+        }
+}
+class Class470 {
+        public Class470(){
+
+        }
+}
+class Class471 {
+        public Class471(){
+
+        }
+}
+class Class472 {
+        public Class472(){
+
+        }
+}
+class Class473 {
+        public Class473(){
+
+        }
+}
+class Class474 {
+        public Class474(){
+
+        }
+}
+class Class475 {
+        public Class475(){
+
+        }
+}
+class Class476 {
+        public Class476(){
+
+        }
+}
+class Class477 {
+        public Class477(){
+
+        }
+}
+class Class478 {
+        public Class478(){
+
+        }
+}
+class Class479 {
+        public Class479(){
+
+        }
+}
+class Class480 {
+        public Class480(){
+
+        }
+}
+class Class481 {
+        public Class481(){
+
+        }
+}
+class Class482 {
+        public Class482(){
+
+        }
+}
+class Class483 {
+        public Class483(){
+
+        }
+}
+class Class484 {
+        public Class484(){
+
+        }
+}
+class Class485 {
+        public Class485(){
+
+        }
+}
+class Class486 {
+        public Class486(){
+
+        }
+}
+class Class487 {
+        public Class487(){
+
+        }
+}
+class Class488 {
+        public Class488(){
+
+        }
+}
+class Class489 {
+        public Class489(){
+
+        }
+}
+class Class490 {
+        public Class490(){
+
+        }
+}
+class Class491 {
+        public Class491(){
+
+        }
+}
+class Class492 {
+        public Class492(){
+
+        }
+}
+class Class493 {
+        public Class493(){
+
+        }
+}
+class Class494 {
+        public Class494(){
+
+        }
+}
+class Class495 {
+        public Class495(){
+
+        }
+}
+class Class496 {
+        public Class496(){
+
+        }
+}
+class Class497 {
+        public Class497(){
+
+        }
+}
+class Class498 {
+        public Class498(){
+
+        }
+}
+class Class499 {
+        public Class499(){
+
+        }
+}
+class Class500 {
+        public Class500(){
+
+        }
+}
+class Class501 {
+        public Class501(){
+
+        }
+}
+class Class502 {
+        public Class502(){
+
+        }
+}
+class Class503 {
+        public Class503(){
+
+        }
+}
+class Class504 {
+        public Class504(){
+
+        }
+}
+class Class505 {
+        public Class505(){
+
+        }
+}
+class Class506 {
+        public Class506(){
+
+        }
+}
+class Class507 {
+        public Class507(){
+
+        }
+}
+class Class508 {
+        public Class508(){
+
+        }
+}
+class Class509 {
+        public Class509(){
+
+        }
+}
+class Class510 {
+        public Class510(){
+
+        }
+}
+class Class511 {
+        public Class511(){
+
+        }
+}
+class Class512 {
+        public Class512(){
+
+        }
+}
+class Class513 {
+        public Class513(){
+
+        }
+}
+class Class514 {
+        public Class514(){
+
+        }
+}
+class Class515 {
+        public Class515(){
+
+        }
+}
+class Class516 {
+        public Class516(){
+
+        }
+}
+class Class517 {
+        public Class517(){
+
+        }
+}
+class Class518 {
+        public Class518(){
+
+        }
+}
+class Class519 {
+        public Class519(){
+
+        }
+}
+class Class520 {
+        public Class520(){
+
+        }
+}
+class Class521 {
+        public Class521(){
+
+        }
+}
+class Class522 {
+        public Class522(){
+
+        }
+}
+class Class523 {
+        public Class523(){
+
+        }
+}
+class Class524 {
+        public Class524(){
+
+        }
+}
+class Class525 {
+        public Class525(){
+
+        }
+}
+class Class526 {
+        public Class526(){
+
+        }
+}
+class Class527 {
+        public Class527(){
+
+        }
+}
+class Class528 {
+        public Class528(){
+
+        }
+}
+class Class529 {
+        public Class529(){
+
+        }
+}
+class Class530 {
+        public Class530(){
+
+        }
+}
+class Class531 {
+        public Class531(){
+
+        }
+}
+class Class532 {
+        public Class532(){
+
+        }
+}
+class Class533 {
+        public Class533(){
+
+        }
+}
+class Class534 {
+        public Class534(){
+
+        }
+}
+class Class535 {
+        public Class535(){
+
+        }
+}
+class Class536 {
+        public Class536(){
+
+        }
+}
+class Class537 {
+        public Class537(){
+
+        }
+}
+class Class538 {
+        public Class538(){
+
+        }
+}
+class Class539 {
+        public Class539(){
+
+        }
+}
+class Class540 {
+        public Class540(){
+
+        }
+}
+class Class541 {
+        public Class541(){
+
+        }
+}
+class Class542 {
+        public Class542(){
+
+        }
+}
+class Class543 {
+        public Class543(){
+
+        }
+}
+class Class544 {
+        public Class544(){
+
+        }
+}
+class Class545 {
+        public Class545(){
+
+        }
+}
+class Class546 {
+        public Class546(){
+
+        }
+}
+class Class547 {
+        public Class547(){
+
+        }
+}
+class Class548 {
+        public Class548(){
+
+        }
+}
+class Class549 {
+        public Class549(){
+
+        }
+}
+class Class550 {
+        public Class550(){
+
+        }
+}
+class Class551 {
+        public Class551(){
+
+        }
+}
+class Class552 {
+        public Class552(){
+
+        }
+}
+class Class553 {
+        public Class553(){
+
+        }
+}
+class Class554 {
+        public Class554(){
+
+        }
+}
+class Class555 {
+        public Class555(){
+
+        }
+}
+class Class556 {
+        public Class556(){
+
+        }
+}
+class Class557 {
+        public Class557(){
+
+        }
+}
+class Class558 {
+        public Class558(){
+
+        }
+}
+class Class559 {
+        public Class559(){
+
+        }
+}
+class Class560 {
+        public Class560(){
+
+        }
+}
+class Class561 {
+        public Class561(){
+
+        }
+}
+class Class562 {
+        public Class562(){
+
+        }
+}
+class Class563 {
+        public Class563(){
+
+        }
+}
+class Class564 {
+        public Class564(){
+
+        }
+}
+class Class565 {
+        public Class565(){
+
+        }
+}
+class Class566 {
+        public Class566(){
+
+        }
+}
+class Class567 {
+        public Class567(){
+
+        }
+}
+class Class568 {
+        public Class568(){
+
+        }
+}
+class Class569 {
+        public Class569(){
+
+        }
+}
+class Class570 {
+        public Class570(){
+
+        }
+}
+class Class571 {
+        public Class571(){
+
+        }
+}
+class Class572 {
+        public Class572(){
+
+        }
+}
+class Class573 {
+        public Class573(){
+
+        }
+}
+class Class574 {
+        public Class574(){
+
+        }
+}
+class Class575 {
+        public Class575(){
+
+        }
+}
+class Class576 {
+        public Class576(){
+
+        }
+}
+class Class577 {
+        public Class577(){
+
+        }
+}
+class Class578 {
+        public Class578(){
+
+        }
+}
+class Class579 {
+        public Class579(){
+
+        }
+}
+class Class580 {
+        public Class580(){
+
+        }
+}
+class Class581 {
+        public Class581(){
+
+        }
+}
+class Class582 {
+        public Class582(){
+
+        }
+}
+class Class583 {
+        public Class583(){
+
+        }
+}
+class Class584 {
+        public Class584(){
+
+        }
+}
+class Class585 {
+        public Class585(){
+
+        }
+}
+class Class586 {
+        public Class586(){
+
+        }
+}
+class Class587 {
+        public Class587(){
+
+        }
+}
+class Class588 {
+        public Class588(){
+
+        }
+}
+class Class589 {
+        public Class589(){
+
+        }
+}
+class Class590 {
+        public Class590(){
+
+        }
+}
+class Class591 {
+        public Class591(){
+
+        }
+}
+class Class592 {
+        public Class592(){
+
+        }
+}
+class Class593 {
+        public Class593(){
+
+        }
+}
+class Class594 {
+        public Class594(){
+
+        }
+}
+class Class595 {
+        public Class595(){
+
+        }
+}
+class Class596 {
+        public Class596(){
+
+        }
+}
+class Class597 {
+        public Class597(){
+
+        }
+}
+class Class598 {
+        public Class598(){
+
+        }
+}
+class Class599 {
+        public Class599(){
+
+        }
+}
+class Class600 {
+        public Class600(){
+
+        }
+}
+class Class601 {
+        public Class601(){
+
+        }
+}
+class Class602 {
+        public Class602(){
+
+        }
+}
+class Class603 {
+        public Class603(){
+
+        }
+}
+class Class604 {
+        public Class604(){
+
+        }
+}
+class Class605 {
+        public Class605(){
+
+        }
+}
+class Class606 {
+        public Class606(){
+
+        }
+}
+class Class607 {
+        public Class607(){
+
+        }
+}
+class Class608 {
+        public Class608(){
+
+        }
+}
+class Class609 {
+        public Class609(){
+
+        }
+}
+class Class610 {
+        public Class610(){
+
+        }
+}
+class Class611 {
+        public Class611(){
+
+        }
+}
+class Class612 {
+        public Class612(){
+
+        }
+}
+class Class613 {
+        public Class613(){
+
+        }
+}
+class Class614 {
+        public Class614(){
+
+        }
+}
+class Class615 {
+        public Class615(){
+
+        }
+}
+class Class616 {
+        public Class616(){
+
+        }
+}
+class Class617 {
+        public Class617(){
+
+        }
+}
+class Class618 {
+        public Class618(){
+
+        }
+}
+class Class619 {
+        public Class619(){
+
+        }
+}
+class Class620 {
+        public Class620(){
+
+        }
+}
+class Class621 {
+        public Class621(){
+
+        }
+}
+class Class622 {
+        public Class622(){
+
+        }
+}
+class Class623 {
+        public Class623(){
+
+        }
+}
+class Class624 {
+        public Class624(){
+
+        }
+}
+class Class625 {
+        public Class625(){
+
+        }
+}
+class Class626 {
+        public Class626(){
+
+        }
+}
+class Class627 {
+        public Class627(){
+
+        }
+}
+class Class628 {
+        public Class628(){
+
+        }
+}
+class Class629 {
+        public Class629(){
+
+        }
+}
+class Class630 {
+        public Class630(){
+
+        }
+}
+class Class631 {
+        public Class631(){
+
+        }
+}
+class Class632 {
+        public Class632(){
+
+        }
+}
+class Class633 {
+        public Class633(){
+
+        }
+}
+class Class634 {
+        public Class634(){
+
+        }
+}
+class Class635 {
+        public Class635(){
+
+        }
+}
+class Class636 {
+        public Class636(){
+
+        }
+}
+class Class637 {
+        public Class637(){
+
+        }
+}
+class Class638 {
+        public Class638(){
+
+        }
+}
+class Class639 {
+        public Class639(){
+
+        }
+}
+class Class640 {
+        public Class640(){
+
+        }
+}
+class Class641 {
+        public Class641(){
+
+        }
+}
+class Class642 {
+        public Class642(){
+
+        }
+}
+class Class643 {
+        public Class643(){
+
+        }
+}
+class Class644 {
+        public Class644(){
+
+        }
+}
+class Class645 {
+        public Class645(){
+
+        }
+}
+class Class646 {
+        public Class646(){
+
+        }
+}
+class Class647 {
+        public Class647(){
+
+        }
+}
+class Class648 {
+        public Class648(){
+
+        }
+}
+class Class649 {
+        public Class649(){
+
+        }
+}
+class Class650 {
+        public Class650(){
+
+        }
+}
+class Class651 {
+        public Class651(){
+
+        }
+}
+class Class652 {
+        public Class652(){
+
+        }
+}
+class Class653 {
+        public Class653(){
+
+        }
+}
+class Class654 {
+        public Class654(){
+
+        }
+}
+class Class655 {
+        public Class655(){
+
+        }
+}
+class Class656 {
+        public Class656(){
+
+        }
+}
+class Class657 {
+        public Class657(){
+
+        }
+}
+class Class658 {
+        public Class658(){
+
+        }
+}
+class Class659 {
+        public Class659(){
+
+        }
+}
+class Class660 {
+        public Class660(){
+
+        }
+}
+class Class661 {
+        public Class661(){
+
+        }
+}
+class Class662 {
+        public Class662(){
+
+        }
+}
+class Class663 {
+        public Class663(){
+
+        }
+}
+class Class664 {
+        public Class664(){
+
+        }
+}
+class Class665 {
+        public Class665(){
+
+        }
+}
+class Class666 {
+        public Class666(){
+
+        }
+}
+class Class667 {
+        public Class667(){
+
+        }
+}
+class Class668 {
+        public Class668(){
+
+        }
+}
+class Class669 {
+        public Class669(){
+
+        }
+}
+class Class670 {
+        public Class670(){
+
+        }
+}
+class Class671 {
+        public Class671(){
+
+        }
+}
+class Class672 {
+        public Class672(){
+
+        }
+}
+class Class673 {
+        public Class673(){
+
+        }
+}
+class Class674 {
+        public Class674(){
+
+        }
+}
+class Class675 {
+        public Class675(){
+
+        }
+}
+class Class676 {
+        public Class676(){
+
+        }
+}
+class Class677 {
+        public Class677(){
+
+        }
+}
+class Class678 {
+        public Class678(){
+
+        }
+}
+class Class679 {
+        public Class679(){
+
+        }
+}
+class Class680 {
+        public Class680(){
+
+        }
+}
+class Class681 {
+        public Class681(){
+
+        }
+}
+class Class682 {
+        public Class682(){
+
+        }
+}
+class Class683 {
+        public Class683(){
+
+        }
+}
+class Class684 {
+        public Class684(){
+
+        }
+}
+class Class685 {
+        public Class685(){
+
+        }
+}
+class Class686 {
+        public Class686(){
+
+        }
+}
+class Class687 {
+        public Class687(){
+
+        }
+}
+class Class688 {
+        public Class688(){
+
+        }
+}
+class Class689 {
+        public Class689(){
+
+        }
+}
+class Class690 {
+        public Class690(){
+
+        }
+}
+class Class691 {
+        public Class691(){
+
+        }
+}
+class Class692 {
+        public Class692(){
+
+        }
+}
+class Class693 {
+        public Class693(){
+
+        }
+}
+class Class694 {
+        public Class694(){
+
+        }
+}
+class Class695 {
+        public Class695(){
+
+        }
+}
+class Class696 {
+        public Class696(){
+
+        }
+}
+class Class697 {
+        public Class697(){
+
+        }
+}
+class Class698 {
+        public Class698(){
+
+        }
+}
+class Class699 {
+        public Class699(){
+
+        }
+}
+class Class700 {
+        public Class700(){
+
+        }
+}
+class Class701 {
+        public Class701(){
+
+        }
+}
+class Class702 {
+        public Class702(){
+
+        }
+}
+class Class703 {
+        public Class703(){
+
+        }
+}
+class Class704 {
+        public Class704(){
+
+        }
+}
+class Class705 {
+        public Class705(){
+
+        }
+}
+class Class706 {
+        public Class706(){
+
+        }
+}
+class Class707 {
+        public Class707(){
+
+        }
+}
+class Class708 {
+        public Class708(){
+
+        }
+}
+class Class709 {
+        public Class709(){
+
+        }
+}
+class Class710 {
+        public Class710(){
+
+        }
+}
+class Class711 {
+        public Class711(){
+
+        }
+}
+class Class712 {
+        public Class712(){
+
+        }
+}
+class Class713 {
+        public Class713(){
+
+        }
+}
+class Class714 {
+        public Class714(){
+
+        }
+}
+class Class715 {
+        public Class715(){
+
+        }
+}
+class Class716 {
+        public Class716(){
+
+        }
+}
+class Class717 {
+        public Class717(){
+
+        }
+}
+class Class718 {
+        public Class718(){
+
+        }
+}
+class Class719 {
+        public Class719(){
+
+        }
+}
+class Class720 {
+        public Class720(){
+
+        }
+}
+class Class721 {
+        public Class721(){
+
+        }
+}
+class Class722 {
+        public Class722(){
+
+        }
+}
+class Class723 {
+        public Class723(){
+
+        }
+}
+class Class724 {
+        public Class724(){
+
+        }
+}
+class Class725 {
+        public Class725(){
+
+        }
+}
+class Class726 {
+        public Class726(){
+
+        }
+}
+class Class727 {
+        public Class727(){
+
+        }
+}
+class Class728 {
+        public Class728(){
+
+        }
+}
+class Class729 {
+        public Class729(){
+
+        }
+}
+class Class730 {
+        public Class730(){
+
+        }
+}
+class Class731 {
+        public Class731(){
+
+        }
+}
+class Class732 {
+        public Class732(){
+
+        }
+}
+class Class733 {
+        public Class733(){
+
+        }
+}
+class Class734 {
+        public Class734(){
+
+        }
+}
+class Class735 {
+        public Class735(){
+
+        }
+}
+class Class736 {
+        public Class736(){
+
+        }
+}
+class Class737 {
+        public Class737(){
+
+        }
+}
+class Class738 {
+        public Class738(){
+
+        }
+}
+class Class739 {
+        public Class739(){
+
+        }
+}
+class Class740 {
+        public Class740(){
+
+        }
+}
+class Class741 {
+        public Class741(){
+
+        }
+}
+class Class742 {
+        public Class742(){
+
+        }
+}
+class Class743 {
+        public Class743(){
+
+        }
+}
+class Class744 {
+        public Class744(){
+
+        }
+}
+class Class745 {
+        public Class745(){
+
+        }
+}
+class Class746 {
+        public Class746(){
+
+        }
+}
+class Class747 {
+        public Class747(){
+
+        }
+}
+class Class748 {
+        public Class748(){
+
+        }
+}
+class Class749 {
+        public Class749(){
+
+        }
+}
+class Class750 {
+        public Class750(){
+
+        }
+}
+class Class751 {
+        public Class751(){
+
+        }
+}
+class Class752 {
+        public Class752(){
+
+        }
+}
+class Class753 {
+        public Class753(){
+
+        }
+}
+class Class754 {
+        public Class754(){
+
+        }
+}
+class Class755 {
+        public Class755(){
+
+        }
+}
+class Class756 {
+        public Class756(){
+
+        }
+}
+class Class757 {
+        public Class757(){
+
+        }
+}
+class Class758 {
+        public Class758(){
+
+        }
+}
+class Class759 {
+        public Class759(){
+
+        }
+}
+class Class760 {
+        public Class760(){
+
+        }
+}
+class Class761 {
+        public Class761(){
+
+        }
+}
+class Class762 {
+        public Class762(){
+
+        }
+}
+class Class763 {
+        public Class763(){
+
+        }
+}
+class Class764 {
+        public Class764(){
+
+        }
+}
+class Class765 {
+        public Class765(){
+
+        }
+}
+class Class766 {
+        public Class766(){
+
+        }
+}
+class Class767 {
+        public Class767(){
+
+        }
+}
+class Class768 {
+        public Class768(){
+
+        }
+}
+class Class769 {
+        public Class769(){
+
+        }
+}
+class Class770 {
+        public Class770(){
+
+        }
+}
+class Class771 {
+        public Class771(){
+
+        }
+}
+class Class772 {
+        public Class772(){
+
+        }
+}
+class Class773 {
+        public Class773(){
+
+        }
+}
+class Class774 {
+        public Class774(){
+
+        }
+}
+class Class775 {
+        public Class775(){
+
+        }
+}
+class Class776 {
+        public Class776(){
+
+        }
+}
+class Class777 {
+        public Class777(){
+
+        }
+}
+class Class778 {
+        public Class778(){
+
+        }
+}
+class Class779 {
+        public Class779(){
+
+        }
+}
+class Class780 {
+        public Class780(){
+
+        }
+}
+class Class781 {
+        public Class781(){
+
+        }
+}
+class Class782 {
+        public Class782(){
+
+        }
+}
+class Class783 {
+        public Class783(){
+
+        }
+}
+class Class784 {
+        public Class784(){
+
+        }
+}
+class Class785 {
+        public Class785(){
+
+        }
+}
+class Class786 {
+        public Class786(){
+
+        }
+}
+class Class787 {
+        public Class787(){
+
+        }
+}
+class Class788 {
+        public Class788(){
+
+        }
+}
+class Class789 {
+        public Class789(){
+
+        }
+}
+class Class790 {
+        public Class790(){
+
+        }
+}
+class Class791 {
+        public Class791(){
+
+        }
+}
+class Class792 {
+        public Class792(){
+
+        }
+}
+class Class793 {
+        public Class793(){
+
+        }
+}
+class Class794 {
+        public Class794(){
+
+        }
+}
+class Class795 {
+        public Class795(){
+
+        }
+}
+class Class796 {
+        public Class796(){
+
+        }
+}
+class Class797 {
+        public Class797(){
+
+        }
+}
+class Class798 {
+        public Class798(){
+
+        }
+}
+class Class799 {
+        public Class799(){
+
+        }
+}
+class Class800 {
+        public Class800(){
+
+        }
+}
+class Class801 {
+        public Class801(){
+
+        }
+}
+class Class802 {
+        public Class802(){
+
+        }
+}
+class Class803 {
+        public Class803(){
+
+        }
+}
+class Class804 {
+        public Class804(){
+
+        }
+}
+class Class805 {
+        public Class805(){
+
+        }
+}
+class Class806 {
+        public Class806(){
+
+        }
+}
+class Class807 {
+        public Class807(){
+
+        }
+}
+class Class808 {
+        public Class808(){
+
+        }
+}
+class Class809 {
+        public Class809(){
+
+        }
+}
+class Class810 {
+        public Class810(){
+
+        }
+}
+class Class811 {
+        public Class811(){
+
+        }
+}
+class Class812 {
+        public Class812(){
+
+        }
+}
+class Class813 {
+        public Class813(){
+
+        }
+}
+class Class814 {
+        public Class814(){
+
+        }
+}
+class Class815 {
+        public Class815(){
+
+        }
+}
+class Class816 {
+        public Class816(){
+
+        }
+}
+class Class817 {
+        public Class817(){
+
+        }
+}
+class Class818 {
+        public Class818(){
+
+        }
+}
+class Class819 {
+        public Class819(){
+
+        }
+}
+class Class820 {
+        public Class820(){
+
+        }
+}
+class Class821 {
+        public Class821(){
+
+        }
+}
+class Class822 {
+        public Class822(){
+
+        }
+}
+class Class823 {
+        public Class823(){
+
+        }
+}
+class Class824 {
+        public Class824(){
+
+        }
+}
+class Class825 {
+        public Class825(){
+
+        }
+}
+class Class826 {
+        public Class826(){
+
+        }
+}
+class Class827 {
+        public Class827(){
+
+        }
+}
+class Class828 {
+        public Class828(){
+
+        }
+}
+class Class829 {
+        public Class829(){
+
+        }
+}
+class Class830 {
+        public Class830(){
+
+        }
+}
+class Class831 {
+        public Class831(){
+
+        }
+}
+class Class832 {
+        public Class832(){
+
+        }
+}
+class Class833 {
+        public Class833(){
+
+        }
+}
+class Class834 {
+        public Class834(){
+
+        }
+}
+class Class835 {
+        public Class835(){
+
+        }
+}
+class Class836 {
+        public Class836(){
+
+        }
+}
+class Class837 {
+        public Class837(){
+
+        }
+}
+class Class838 {
+        public Class838(){
+
+        }
+}
+class Class839 {
+        public Class839(){
+
+        }
+}
+class Class840 {
+        public Class840(){
+
+        }
+}
+class Class841 {
+        public Class841(){
+
+        }
+}
+class Class842 {
+        public Class842(){
+
+        }
+}
+class Class843 {
+        public Class843(){
+
+        }
+}
+class Class844 {
+        public Class844(){
+
+        }
+}
+class Class845 {
+        public Class845(){
+
+        }
+}
+class Class846 {
+        public Class846(){
+
+        }
+}
+class Class847 {
+        public Class847(){
+
+        }
+}
+class Class848 {
+        public Class848(){
+
+        }
+}
+class Class849 {
+        public Class849(){
+
+        }
+}
+class Class850 {
+        public Class850(){
+
+        }
+}
+class Class851 {
+        public Class851(){
+
+        }
+}
+class Class852 {
+        public Class852(){
+
+        }
+}
+class Class853 {
+        public Class853(){
+
+        }
+}
+class Class854 {
+        public Class854(){
+
+        }
+}
+class Class855 {
+        public Class855(){
+
+        }
+}
+class Class856 {
+        public Class856(){
+
+        }
+}
+class Class857 {
+        public Class857(){
+
+        }
+}
+class Class858 {
+        public Class858(){
+
+        }
+}
+class Class859 {
+        public Class859(){
+
+        }
+}
+class Class860 {
+        public Class860(){
+
+        }
+}
+class Class861 {
+        public Class861(){
+
+        }
+}
+class Class862 {
+        public Class862(){
+
+        }
+}
+class Class863 {
+        public Class863(){
+
+        }
+}
+class Class864 {
+        public Class864(){
+
+        }
+}
+class Class865 {
+        public Class865(){
+
+        }
+}
+class Class866 {
+        public Class866(){
+
+        }
+}
+class Class867 {
+        public Class867(){
+
+        }
+}
+class Class868 {
+        public Class868(){
+
+        }
+}
+class Class869 {
+        public Class869(){
+
+        }
+}
+class Class870 {
+        public Class870(){
+
+        }
+}
+class Class871 {
+        public Class871(){
+
+        }
+}
+class Class872 {
+        public Class872(){
+
+        }
+}
+class Class873 {
+        public Class873(){
+
+        }
+}
+class Class874 {
+        public Class874(){
+
+        }
+}
+class Class875 {
+        public Class875(){
+
+        }
+}
+class Class876 {
+        public Class876(){
+
+        }
+}
+class Class877 {
+        public Class877(){
+
+        }
+}
+class Class878 {
+        public Class878(){
+
+        }
+}
+class Class879 {
+        public Class879(){
+
+        }
+}
+class Class880 {
+        public Class880(){
+
+        }
+}
+class Class881 {
+        public Class881(){
+
+        }
+}
+class Class882 {
+        public Class882(){
+
+        }
+}
+class Class883 {
+        public Class883(){
+
+        }
+}
+class Class884 {
+        public Class884(){
+
+        }
+}
+class Class885 {
+        public Class885(){
+
+        }
+}
+class Class886 {
+        public Class886(){
+
+        }
+}
+class Class887 {
+        public Class887(){
+
+        }
+}
+class Class888 {
+        public Class888(){
+
+        }
+}
+class Class889 {
+        public Class889(){
+
+        }
+}
+class Class890 {
+        public Class890(){
+
+        }
+}
+class Class891 {
+        public Class891(){
+
+        }
+}
+class Class892 {
+        public Class892(){
+
+        }
+}
+class Class893 {
+        public Class893(){
+
+        }
+}
+class Class894 {
+        public Class894(){
+
+        }
+}
+class Class895 {
+        public Class895(){
+
+        }
+}
+class Class896 {
+        public Class896(){
+
+        }
+}
+class Class897 {
+        public Class897(){
+
+        }
+}
+class Class898 {
+        public Class898(){
+
+        }
+}
+class Class899 {
+        public Class899(){
+
+        }
+}
+class Class900 {
+        public Class900(){
+
+        }
+}
+class Class901 {
+        public Class901(){
+
+        }
+}
+class Class902 {
+        public Class902(){
+
+        }
+}
+class Class903 {
+        public Class903(){
+
+        }
+}
+class Class904 {
+        public Class904(){
+
+        }
+}
+class Class905 {
+        public Class905(){
+
+        }
+}
+class Class906 {
+        public Class906(){
+
+        }
+}
+class Class907 {
+        public Class907(){
+
+        }
+}
+class Class908 {
+        public Class908(){
+
+        }
+}
+class Class909 {
+        public Class909(){
+
+        }
+}
+class Class910 {
+        public Class910(){
+
+        }
+}
+class Class911 {
+        public Class911(){
+
+        }
+}
+class Class912 {
+        public Class912(){
+
+        }
+}
+class Class913 {
+        public Class913(){
+
+        }
+}
+class Class914 {
+        public Class914(){
+
+        }
+}
+class Class915 {
+        public Class915(){
+
+        }
+}
+class Class916 {
+        public Class916(){
+
+        }
+}
+class Class917 {
+        public Class917(){
+
+        }
+}
+class Class918 {
+        public Class918(){
+
+        }
+}
+class Class919 {
+        public Class919(){
+
+        }
+}
+class Class920 {
+        public Class920(){
+
+        }
+}
+class Class921 {
+        public Class921(){
+
+        }
+}
+class Class922 {
+        public Class922(){
+
+        }
+}
+class Class923 {
+        public Class923(){
+
+        }
+}
+class Class924 {
+        public Class924(){
+
+        }
+}
+class Class925 {
+        public Class925(){
+
+        }
+}
+class Class926 {
+        public Class926(){
+
+        }
+}
+class Class927 {
+        public Class927(){
+
+        }
+}
+class Class928 {
+        public Class928(){
+
+        }
+}
+class Class929 {
+        public Class929(){
+
+        }
+}
+class Class930 {
+        public Class930(){
+
+        }
+}
+class Class931 {
+        public Class931(){
+
+        }
+}
+class Class932 {
+        public Class932(){
+
+        }
+}
+class Class933 {
+        public Class933(){
+
+        }
+}
+class Class934 {
+        public Class934(){
+
+        }
+}
+class Class935 {
+        public Class935(){
+
+        }
+}
+class Class936 {
+        public Class936(){
+
+        }
+}
+class Class937 {
+        public Class937(){
+
+        }
+}
+class Class938 {
+        public Class938(){
+
+        }
+}
+class Class939 {
+        public Class939(){
+
+        }
+}
+class Class940 {
+        public Class940(){
+
+        }
+}
+class Class941 {
+        public Class941(){
+
+        }
+}
+class Class942 {
+        public Class942(){
+
+        }
+}
+class Class943 {
+        public Class943(){
+
+        }
+}
+class Class944 {
+        public Class944(){
+
+        }
+}
+class Class945 {
+        public Class945(){
+
+        }
+}
+class Class946 {
+        public Class946(){
+
+        }
+}
+class Class947 {
+        public Class947(){
+
+        }
+}
+class Class948 {
+        public Class948(){
+
+        }
+}
+class Class949 {
+        public Class949(){
+
+        }
+}
+class Class950 {
+        public Class950(){
+
+        }
+}
+class Class951 {
+        public Class951(){
+
+        }
+}
+class Class952 {
+        public Class952(){
+
+        }
+}
+class Class953 {
+        public Class953(){
+
+        }
+}
+class Class954 {
+        public Class954(){
+
+        }
+}
+class Class955 {
+        public Class955(){
+
+        }
+}
+class Class956 {
+        public Class956(){
+
+        }
+}
+class Class957 {
+        public Class957(){
+
+        }
+}
+class Class958 {
+        public Class958(){
+
+        }
+}
+class Class959 {
+        public Class959(){
+
+        }
+}
+class Class960 {
+        public Class960(){
+
+        }
+}
+class Class961 {
+        public Class961(){
+
+        }
+}
+class Class962 {
+        public Class962(){
+
+        }
+}
+class Class963 {
+        public Class963(){
+
+        }
+}
+class Class964 {
+        public Class964(){
+
+        }
+}
+class Class965 {
+        public Class965(){
+
+        }
+}
+class Class966 {
+        public Class966(){
+
+        }
+}
+class Class967 {
+        public Class967(){
+
+        }
+}
+class Class968 {
+        public Class968(){
+
+        }
+}
+class Class969 {
+        public Class969(){
+
+        }
+}
+class Class970 {
+        public Class970(){
+
+        }
+}
+class Class971 {
+        public Class971(){
+
+        }
+}
+class Class972 {
+        public Class972(){
+
+        }
+}
+class Class973 {
+        public Class973(){
+
+        }
+}
+class Class974 {
+        public Class974(){
+
+        }
+}
+class Class975 {
+        public Class975(){
+
+        }
+}
+class Class976 {
+        public Class976(){
+
+        }
+}
+class Class977 {
+        public Class977(){
+
+        }
+}
+class Class978 {
+        public Class978(){
+
+        }
+}
+class Class979 {
+        public Class979(){
+
+        }
+}
+class Class980 {
+        public Class980(){
+
+        }
+}
+class Class981 {
+        public Class981(){
+
+        }
+}
+class Class982 {
+        public Class982(){
+
+        }
+}
+class Class983 {
+        public Class983(){
+
+        }
+}
+class Class984 {
+        public Class984(){
+
+        }
+}
+class Class985 {
+        public Class985(){
+
+        }
+}
+class Class986 {
+        public Class986(){
+
+        }
+}
+class Class987 {
+        public Class987(){
+
+        }
+}
+class Class988 {
+        public Class988(){
+
+        }
+}
+class Class989 {
+        public Class989(){
+
+        }
+}
+class Class990 {
+        public Class990(){
+
+        }
+}
+class Class991 {
+        public Class991(){
+
+        }
+}
+class Class992 {
+        public Class992(){
+
+        }
+}
+class Class993 {
+        public Class993(){
+
+        }
+}
+class Class994 {
+        public Class994(){
+
+        }
+}
+class Class995 {
+        public Class995(){
+
+        }
+}
+class Class996 {
+        public Class996(){
+
+        }
+}
+class Class997 {
+        public Class997(){
+
+        }
+}
+class Class998 {
+        public Class998(){
+
+        }
+}
+class Class999 {
+        public Class999(){
+
+        }
+}
+class Class1000 {
+        public Class1000(){
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/DerivedProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Garbage producer that uses another garbage producer
+ * to implement it's functionality.
+ */
+public abstract class DerivedProducer<T, P> implements GarbageProducer<T> {
+        private GarbageProducer<P> parent;
+
+        public DerivedProducer(GarbageProducer<P> parent) {
+                setParent(parent);
+        }
+
+        protected P createParent(long memory) {
+                return parent.create(memory);
+        }
+
+        protected void validateParent(P obj) {
+                parent.validate(obj);
+        }
+
+        public final GarbageProducer<P> getParent() {
+                return parent;
+        }
+
+        public final void setParent(GarbageProducer<P> parent) {
+                this.parent = parent;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/DerivedStrategyProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Derived garbage producer that uses a memory strategy.
+ */
+public abstract class DerivedStrategyProducer<T, P> extends DerivedProducer<T, P> {
+        protected MemoryStrategy memoryStrategy;
+
+        public DerivedStrategyProducer(GarbageProducer<P> parent, MemoryStrategy memoryStrategy) {
+                super(parent);
+        }
+
+        public final void setMemoryStrategy(MemoryStrategy memoryStrategy) {
+                this.memoryStrategy = memoryStrategy;
+        }
+
+        public final MemoryStrategy getMemoryStrategy() {
+                return memoryStrategy;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Interface that defines a way to produce garbage.
+ */
+public interface GarbageProducer<T> {
+        /**
+         * Produce garbage of given size.
+         *
+         * @param memory size in bytes
+         * @return produced garbage
+         */
+        public T create(long memory);
+
+        /**
+         * Validate earlier produced object.
+         *
+         * @param obj earlier produced garbage
+         * @throws TestFailure if validation fails
+         */
+        public void validate(T obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducer1Aware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Marker interface for getting GarbageProducer.
+ */
+public interface GarbageProducer1Aware {
+        public void setGarbageProducer1(GarbageProducer gp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducerAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Marker interface for getting GarbageProducer.
+ */
+public interface GarbageProducerAware {
+        public void setGarbageProducer(GarbageProducer gp);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageProducers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+import java.util.List;
+import java.util.ArrayList;
+import nsk.share.gc.gp.array.*;
+import nsk.share.gc.gp.string.*;
+
+/**
+ * Factory for garbage producers
+ */
+public class GarbageProducers {
+        private List<GarbageProducer> primitiveArrayProducers;
+        private List<GarbageProducer> arrayProducers;
+        private List<GarbageProducer<String>> stringProducers;
+        private List<GarbageProducer> allProducers;
+
+        /**
+         * Get all primitive array producers.
+         */
+        public List<GarbageProducer> getPrimitiveArrayProducers() {
+                if (primitiveArrayProducers == null) {
+                        primitiveArrayProducers = new ArrayList<GarbageProducer>();
+                        primitiveArrayProducers.add(new ByteArrayProducer());
+                        primitiveArrayProducers.add(new BooleanArrayProducer());
+                        primitiveArrayProducers.add(new ShortArrayProducer());
+                        primitiveArrayProducers.add(new CharArrayProducer());
+                        primitiveArrayProducers.add(new IntArrayProducer());
+                        primitiveArrayProducers.add(new LongArrayProducer());
+                        primitiveArrayProducers.add(new FloatArrayProducer());
+                        primitiveArrayProducers.add(new DoubleArrayProducer());
+                }
+                return primitiveArrayProducers;
+        }
+
+        /**
+         * Get all array producers.
+         */
+        public List<GarbageProducer> getArrayProducers() {
+                if (arrayProducers == null) {
+                        arrayProducers = new ArrayList<GarbageProducer>();
+                        arrayProducers.addAll(getPrimitiveArrayProducers());
+                        arrayProducers.add(new ObjectArrayProducer());
+                }
+                return arrayProducers;
+        }
+
+        /**
+         * Get all string producers.
+         */
+        public List<GarbageProducer<String>> getStringProducers() {
+                if (stringProducers == null) {
+                        stringProducers = new ArrayList<GarbageProducer<String>>();
+                        stringProducers.add(new RandomStringProducer());
+                        stringProducers.add(new InternedStringProducer());
+                }
+                return stringProducers;
+        }
+
+        public List<GarbageProducer> getAllProducers() {
+                if (allProducers == null) {
+                        allProducers = new ArrayList<GarbageProducer>();
+                        allProducers.addAll(getArrayProducers());
+                        allProducers.addAll(getStringProducers());
+                }
+                return allProducers;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/GarbageUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.*;
+import nsk.share.gc.gp.array.*;
+import nsk.share.gc.gp.string.*;
+import nsk.share.gc.gp.list.*;
+import nsk.share.gc.gp.tree.*;
+import nsk.share.gc.gp.misc.*;
+import nsk.share.gc.gp.classload.*;
+import nsk.share.gc.Memory;
+import nsk.share.TestBug;
+import nsk.share.test.*;
+
+/**
+ * Utility methods for garbage producers.
+ */
+public final class GarbageUtils {
+        private static final int ALLOCATION_LIMIT = 50000000; //50 Mb
+        private static GarbageProducers garbageProducers;
+        private static List<GarbageProducer> primitiveArrayProducers;
+        private static List<GarbageProducer> arrayProducers;
+        private static final GarbageProducer  byteArrayProducer = new ByteArrayProducer();
+        public static enum OOM_TYPE {
+            ANY (),
+            HEAP("Java heap space"),
+            METASPACE("Metaspace", "Compressed class space");
+
+            private final String[] expectedStrings;
+            OOM_TYPE(String... expectedStrings) {
+                this.expectedStrings = expectedStrings;
+            }
+
+            /**
+                         * Returns true if the given error message matches
+                         * one of expected strings.
+                         */
+                        public boolean accept(String errorMessage) {
+                if (expectedStrings == null || expectedStrings.length == 0 || errorMessage == null) {
+                    return true;
+                }
+                for (String s: expectedStrings) {
+                    if (errorMessage.indexOf(s) != -1) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        };
+
+        // Force loading of OOM_TYPE and calling of enum contrusctors when loading GarbageUtils class.
+        public static final Object[] thisIsGarbageArray_theOnlyPurposeForCreatingItAndDeclaringItPublicIsToInitializeIntancesOfOOMEnumberation = new Object[] { OOM_TYPE.ANY, OOM_TYPE.HEAP, OOM_TYPE.METASPACE };
+
+        // Force early loading of classes that might otherwise unexpectedly fail
+        // class loading during testing due to high memory pressure.
+        public static final StringWriter preloadStringWriter = new StringWriter(1);
+        public static final PrintWriter preloadPrintWriter = new PrintWriter(preloadStringWriter);
+
+        private GarbageUtils() {
+        }
+
+        /**
+         * Eat memory using execution controller that waits for 2 minutes.
+         * @return number of OOME occured
+         */
+        public static int eatMemory() {
+                return eatMemory(2 * 60 * 1000);
+        }
+
+        /**
+         * Eat memory using execution controller that waits for timeout.
+         * @return number of OOME occured
+         */
+        public static int eatMemory(final long timeout) {
+                return eatMemory(new ExecutionController() {
+                        final long initialTime = System.currentTimeMillis();
+
+                                @Override
+                                public void start(long stdIterations) {}
+
+                                @Override
+                                public boolean iteration() {return false;}
+
+                                @Override
+                                public boolean continueExecution() {
+                                        return System.currentTimeMillis() - initialTime < timeout;
+                                }
+
+                                @Override
+                                public long getIteration() {return 0;}
+
+                                @Override
+                                public void finish() {}
+                });
+        }
+
+
+        /**
+         * Eat memory using given execution controller and garbage producer.
+         *
+         * @param stresser execution controller
+         * @param gp garbage producer
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser) {
+            return eatMemory(stresser, byteArrayProducer, 50, 100, 2, OOM_TYPE.ANY);
+        }
+
+        /**
+         * Eat memory using given execution controller and garbage producer.
+         *
+         * @param stresser execution controller
+         * @param gp garbage producer
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser, GarbageProducer gp) {
+            return eatMemory(stresser, gp, 50, 100, 2, OOM_TYPE.ANY);
+        }
+
+        /**
+         * Eat memory using given garbage producer and given factor.
+         *
+         * @param gp garbage producer
+         * @param factor factor to divide the array size by
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long factor) {
+            return eatMemory(stresser, gp, 50, 100, factor, OOM_TYPE.ANY);
+        }
+
+        /**
+         * Eat memory using default(byte[]) garbage producer.
+         *
+         * Note that this method can throw Failure if any exception
+         * is thrown while eating memory. To avoid OOM while allocating
+         * exception we preallocate it before the lunch starts. It means
+         * that exception stack trace does not correspond to the place
+         * where exception is thrown, but points at start of the method.
+         *
+         * @param stresser stresser
+         * @param initialFactor determines which portion of initial memory initial chunk will be
+         * @param minMemoryChunk determines when to stop
+         * @param factor factor to divide the array size by
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser,long initialFactor, long minMemoryChunk, long factor) {
+            return eatMemory(stresser, byteArrayProducer, initialFactor, minMemoryChunk, factor, OOM_TYPE.ANY);
+        }
+
+        /**
+         * Eat memory using given garbage producer.
+         *
+         * Note that this method can throw Failure if any exception
+         * is thrown while eating memory. To avoid OOM while allocating
+         * exception we preallocate it before the lunch starts. It means
+         * that exception stack trace does not correspond to the place
+         * where exception is thrown, but points at start of the method.
+         *
+         * @param stresser stresser to use
+         * @param gp garbage producer
+         * @param initialFactor determines which portion of initial memory initial chunk will be
+         * @param minMemoryChunk determines when to stop
+         * @param factor factor to divide the array size by. A value of 0 means that method returns after first  OOME
+         * @param type of OutOfMemory Exception: Java heap space or Metadata space
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long initialFactor, long minMemoryChunk, long factor) {
+            return eatMemory(stresser, gp, initialFactor, minMemoryChunk, factor, OOM_TYPE.ANY);
+        }
+
+        /**
+         * Eat memory using given garbage producer.
+         *
+         * Note that this method can throw Failure if any exception
+         * is thrown while eating memory. To avoid OOM while allocating
+         * exception we preallocate it before the lunch starts. It means
+         * that exception stack trace does not correspond to the place
+         * where exception is thrown, but points at start of the method.
+         *
+         * @param stresser stresser to use
+         * @param gp garbage producer
+         * @param initialFactor determines which portion of initial memory initial chunk will be
+         * @param minMemoryChunk determines when to stop
+         * @param factor factor to divide the array size by. A value of 0 means that method returns after first  OOME
+         * @param type of OutOfMemory Exception: Java heap space or Metadata space
+         * @return number of OOME occured
+         */
+        public static int eatMemory(ExecutionController stresser, GarbageProducer gp, long initialFactor, long minMemoryChunk, long factor, OOM_TYPE type) {
+                int numberOfOOMEs = 0;
+                try {
+                        StringWriter sw = new StringWriter(10000);
+                        PrintWriter pw = new PrintWriter(sw);
+                        byte[] someMemory = new byte[200000]; //200 Kb
+                        try {
+                                Runtime runtime = Runtime.getRuntime();
+                                long maxMemory = runtime.maxMemory();
+                                long maxMemoryChunk = maxMemory / initialFactor;
+                                long chunk = maxMemoryChunk;
+                                chunk = chunk > ALLOCATION_LIMIT ? ALLOCATION_LIMIT : chunk;
+                                int allocations = 0;
+                                List<Object> storage = new ArrayList<Object>();
+
+                                while (chunk > minMemoryChunk && stresser.continueExecution()) {
+                                        try {
+                                                storage.add(gp.create(chunk));
+                                                if (Thread.currentThread().isInterrupted()) {
+                                                        return numberOfOOMEs;
+                                                }
+                                                // if we are able to eat chunk*factor let
+                                                // try to increase size of chunk
+                                                if (chunk * factor < maxMemoryChunk
+                                                        && factor != 0 && allocations++ == factor + 1) {
+                                                    chunk = chunk * factor;
+                                                    allocations = 0;
+                                                }
+                                        } catch (OutOfMemoryError e) {
+                                            someMemory = null;
+                                            if (type != OOM_TYPE.ANY) {
+                                                e.printStackTrace(pw);
+                                                pw.close();
+                                                if (type.accept(sw.toString())) {
+                                                    numberOfOOMEs++;
+                                                } else {
+                                                    // Trying to catch situation when Java generates OOM different type that test trying to catch
+                                                    throw new TestBug("Test throw OOM of unexpected type." + sw.toString());
+                                                }
+                                            } else {
+                                               numberOfOOMEs++;
+                                            }
+                                            allocations = 0;
+                                            if (factor == 0) {
+                                                return numberOfOOMEs;
+                                            } else {
+                                                chunk = chunk / factor;
+                                            }
+                                        }
+                                }
+                        } catch (OutOfMemoryError e) {
+                            someMemory = null;
+                            if (type != OOM_TYPE.ANY) {
+                                e.printStackTrace(pw);
+                                pw.close();
+                                if (type.accept(sw.toString())) {
+                                    numberOfOOMEs++;
+                                } else {
+                                    // Trying to catch situation when Java generates OOM different type that test trying to catch
+                                    throw new TestBug("Test throw OOM of unexpected type." + sw.toString());
+                                }
+                            } else {
+                                numberOfOOMEs++;
+                            }
+                         // all memory is eaten now even before we start, just return
+                        }
+                } catch (OutOfMemoryError e) {
+                        numberOfOOMEs++;
+                }
+                return numberOfOOMEs;
+        }
+
+        /**
+         * Get all primitive array producers.
+         */
+        public static List<GarbageProducer> getPrimitiveArrayProducers() {
+                return getGarbageProducers().getPrimitiveArrayProducers();
+        }
+
+        /**
+         * Get all array producers.
+         */
+        public static List<GarbageProducer> getArrayProducers() {
+                return getGarbageProducers().getArrayProducers();
+        }
+
+        /**
+         * Determine size of each object in array which will occupy given
+         * memory with distribution determined by given memory strategy.
+         */
+        public static long getArraySize(long memory, MemoryStrategy memoryStrategy) {
+                return memoryStrategy.getSize(memory - Memory.getArrayExtraSize(), Memory.getReferenceSize());
+        }
+
+        /**
+         * Determine object count in array which will occupy given
+         * memory with distribution determined by given memory strategy.
+         */
+        public static int getArrayCount(long memory, MemoryStrategy memoryStrategy) {
+                return memoryStrategy.getCount(memory - Memory.getArrayExtraSize(), Memory.getReferenceSize());
+        }
+
+        /**
+         * Get garbage producer by identifier.
+         *
+         * @param id identifier
+         * @return garbage producer for this identifier
+         */
+        public static GarbageProducer getGarbageProducer(String id) {
+                if (id == null || id.equals("byteArr"))
+                        return new ByteArrayProducer();
+                else if (id.equals("booleanArr"))
+                        return new BooleanArrayProducer();
+                else if (id.equals("shortArr"))
+                        return new ShortArrayProducer();
+                else if (id.equals("charArr"))
+                        return new CharArrayProducer();
+                else if (id.equals("intArr"))
+                        return new IntArrayProducer();
+                else if (id.equals("longArr"))
+                        return new LongArrayProducer();
+                else if (id.equals("floatArr"))
+                        return new FloatArrayProducer();
+                else if (id.equals("doubleArr"))
+                        return new DoubleArrayProducer();
+                else if (id.equals("objectArr"))
+                        return new ObjectArrayProducer();
+                else if (id.equals("randomString"))
+                        return new RandomStringProducer();
+                else if (id.equals("simpleString"))
+                        return new SimpleStringProducer();
+                else if (id.startsWith("interned("))
+                        return new InternedStringProducer(getGarbageProducer(getInBrackets(id)));
+                else if (id.startsWith("linearList("))
+                        return new LinearListProducer(MemoryStrategy.fromString(getInBrackets(id)));
+                else if (id.startsWith("circularList("))
+                        return new CircularListProducer(MemoryStrategy.fromString(getInBrackets(id)));
+                else if (id.startsWith("nonbranchyTree("))
+                        return new NonbranchyTreeProducer(MemoryStrategy.fromString(getInBrackets(id)));
+                else if (id.equals("class"))
+                        return new GeneratedClassProducer();
+                else if (id.startsWith("hashed("))
+                        return new HashedGarbageProducer(getGarbageProducer(getInBrackets(id)));
+                else if (id.startsWith("random("))
+                        return new RandomProducer(getGarbageProducerList(getInBrackets(id)));
+                else if (id.startsWith("twofields("))
+                        return new TwoFieldsObjectProducer(getGarbageProducer(getInBrackets(id)));
+                else if (id.startsWith("arrayof("))
+                        return new ArrayOfProducer(getGarbageProducer(getInBrackets(id)));
+                else if (id.startsWith("trace("))
+                        return new TraceProducer(getGarbageProducer(getInBrackets(id)));
+                else
+                        throw new TestBug("Invalid garbage producer identifier: " + id);
+        }
+
+        private static String getInBrackets(String s) {
+                int n1 = s.indexOf('(');
+                if (n1 == -1)
+                        throw new TestBug("Opening bracket not found: " + s);
+                int n2 = s.lastIndexOf(')');
+                if (n2 == -1)
+                        throw new TestBug("Closing bracket not found: " + s);
+                return s.substring(n1 + 1, n2);
+        }
+
+        private static List<GarbageProducer> getGarbageProducerList(String s) {
+                if (s.equals("primitiveArrays"))
+                        return getPrimitiveArrayProducers();
+                else if (s.equals("arrays"))
+                        return getArrayProducers();
+                else {
+                        String[] ids = s.split(",");
+                        List<GarbageProducer> garbageProducers = new ArrayList<GarbageProducer>(ids.length);
+                        for (int i = 0; i < ids.length; ++i)
+                                garbageProducers.add(getGarbageProducer(ids[i]));
+                        return garbageProducers;
+                        //throw new TestBug("Invalid id for list of garbage producers: " + id);
+                }
+        }
+
+        public static GarbageProducers getGarbageProducers() {
+                if (garbageProducers == null)
+                        garbageProducers = new GarbageProducers();
+                return garbageProducers;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/MemoryStrategy.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+import nsk.share.TestBug;
+
+/**
+ * This class encapsulates notions like "many objects of small size",
+ * "small number of objects of big size".
+ */
+public abstract class MemoryStrategy {
+        private static int smallNumber = 100;
+        public abstract long getSize(long memory);
+        public abstract long getSize(long memory, long objectExtra);
+        public abstract int getCount(long memory);
+        public abstract int getCount(long memory, long objectExtra);
+
+        protected MemoryStrategy() {
+        }
+
+        /**
+         * Small object size, big number of objects.
+         */
+        public static final MemoryStrategy LOW = new MemoryStrategy() {
+                public long getSize(long memory) {
+                        return getSize(memory, 0);
+                }
+
+                public long getSize(long memory, long objectExtra) {
+                        return smallNumber;
+                }
+
+                public int getCount(long memory) {
+                        return getCount(memory, 0);
+                }
+
+                public int getCount(long memory, long objectExtra) {
+                        return (int) Math.min(Integer.MAX_VALUE, memory / (getSize(memory) + objectExtra));
+                }
+
+                public String toString() {
+                        return "low";
+                }
+        };
+
+        /**
+         * Medium object size, medium number of objects.
+         */
+        public static final MemoryStrategy MEDIUM = new MemoryStrategy() {
+                public long getSize(long memory) {
+                        return getSize(memory, 0);
+                }
+
+                public long getSize(long memory, long objectExtra) {
+                        return Math.round(Math.floor(Math.sqrt(memory)));
+                }
+
+                public int getCount(long memory) {
+                        return getCount(memory, 0);
+                }
+
+                public int getCount(long memory, long objectExtra) {
+                        return (int) Math.min(Integer.MAX_VALUE, memory / (getSize(memory) + objectExtra));
+                }
+
+                public String toString() {
+                        return "medium";
+                }
+        };
+
+        /**
+         * Big object size, small number of objects.
+         */
+        public static final MemoryStrategy HIGH = new MemoryStrategy() {
+                public long getSize(long memory) {
+                        return getSize(memory, 0);
+                }
+
+                public long getSize(long memory, long objectExtra) {
+                        return memory / getCount(memory, objectExtra);
+                }
+
+                public int getCount(long memory) {
+                        return getCount(memory, 0);
+                }
+
+                public int getCount(long memory, long objectExtra) {
+                        return smallNumber;
+                }
+
+                public String toString() {
+                        return "high";
+                }
+        };
+
+        /**
+         * Get memory strategy by identifier.
+         *
+         * @param id identifier
+         * @return memory strategy for this identifier
+         * @throws TestBug if id is invalid
+         */
+        public static MemoryStrategy fromString(String id) {
+                if (id.equalsIgnoreCase("low"))
+                        return LOW;
+                else if (id.equalsIgnoreCase("medium"))
+                        return MEDIUM;
+                else if (id.equalsIgnoreCase("high"))
+                        return HIGH;
+                else
+                        throw new TestBug("Unknown memory strategy identifier: " + id);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/MemoryStrategyAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+/**
+ * Marker interface for getting MemoryStrategy.
+ */
+public interface MemoryStrategyAware {
+        public void setMemoryStrategy(MemoryStrategy memoryStrategy);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/RandomProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp;
+
+import java.util.List;
+import nsk.share.test.LocalRandom;
+
+/**
+ * Garbage producer that randomly creates objects using
+ * one garbage producer from the list.
+ */
+public class RandomProducer<T> implements GarbageProducer<T> {
+        private List<GarbageProducer<T>> producers;
+
+        public RandomProducer(List<GarbageProducer<T>> producers) {
+                this.producers = producers;
+        }
+
+        public T create(long memory) {
+                return producers.get(LocalRandom.nextInt(producers.size())).create(memory);
+        }
+
+        public void validate(T obj) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ArrayOfProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.DerivedProducer;
+import nsk.share.gc.gp.GarbageUtils;
+import nsk.share.gc.gp.MemoryStrategy;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces arrays of objects
+ * determined by parent garbage producer. A memory strategy is
+ * used to determine how memory is distributed between array size
+ * and size of each object in array.
+ */
+public class ArrayOfProducer<T> extends DerivedProducer<Object[], T> {
+        private int n;
+
+        public ArrayOfProducer(GarbageProducer<T> parent, int n) {
+                super(parent);
+                this.n = n;
+        }
+
+        public ArrayOfProducer(GarbageProducer<T> parent) {
+                this(parent, 2);
+        }
+
+        public Object[] create(long memory) {
+                Object[] array = new Object[n];
+                long objectSize = (memory - Memory.getArrayExtraSize() - Memory.getReferenceSize() * n) / n;
+                for (int i = 0; i < n; ++i)
+                        array[i] = createParent(objectSize);
+                return array;
+        }
+
+        public void validate(Object[] obj) {
+                for (int i = 0; i < obj.length; ++i)
+                        validateParent((T) obj[i]);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.DerivedStrategyProducer;
+import nsk.share.gc.gp.GarbageUtils;
+import nsk.share.gc.gp.MemoryStrategy;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces arrays of objects
+ * determined by parent garbage producer. A memory strategy is
+ * used to determine how memory is distributed between array size
+ * and size of each object in array.
+ */
+public class ArrayProducer<T> extends DerivedStrategyProducer<Object[], T> {
+        public ArrayProducer(GarbageProducer<T> parent, MemoryStrategy memoryStrategy) {
+                super(parent, memoryStrategy);
+        }
+
+        public Object[] create(long memory) {
+                long objectSize = GarbageUtils.getArraySize(memory, memoryStrategy);
+                int objectCount = GarbageUtils.getArrayCount(memory, memoryStrategy);
+                Object[] array = new Object[objectCount];
+                for (int i = 0; i < objectCount; ++i)
+                        array[i] = createParent(objectSize);
+                return array;
+        }
+
+        public void validate(Object[] obj) {
+                for (int i = 0; i < obj.length; ++i)
+                        validateParent((T) obj[i]);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/BooleanArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces byte arrays.
+ */
+public class BooleanArrayProducer implements GarbageProducer<boolean[]> {
+        public boolean[] create(long memory) {
+                boolean[] arr = new boolean[Memory.getArrayLength(memory, Memory.getBooleanSize())];
+                LocalRandom.nextBooleans(arr);
+                return arr;
+        }
+
+        public void validate(boolean[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ByteArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces byte arrays.
+ */
+public class ByteArrayProducer implements GarbageProducer<byte[]> {
+        public byte[] create(long memory) {
+                byte[] arr = new byte[Memory.getArrayLength(memory, 1)];
+                LocalRandom.nextBytes(arr);
+                return arr;
+        }
+
+        public void validate(byte[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/CharArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces int arrays.
+ */
+public class CharArrayProducer implements GarbageProducer<char[]> {
+        public char[] create(long memory) {
+                char[] arr = new char[Memory.getArrayLength(memory, Memory.getCharSize())];
+                LocalRandom.nextChars(arr);
+                return arr;
+        }
+
+        public void validate(char[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/DoubleArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+
+/**
+ * GarbageProducer implementation that produces double arrays.
+ */
+public class DoubleArrayProducer implements GarbageProducer<double[]> {
+        public double[] create(long memory) {
+                double[] arr = new double[Memory.getArrayLength(memory, Memory.getDoubleSize())];
+                LocalRandom.nextDoubles(arr);
+                return arr;
+        }
+
+        public void validate(double[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/FloatArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+
+/**
+ * GarbageProducer implementation that produces float arrays.
+ */
+public class FloatArrayProducer implements GarbageProducer<float[]> {
+        public float[] create(long memory) {
+                float[] arr = new float[Memory.getArrayLength(memory, Memory.getFloatSize())];
+                LocalRandom.nextFloats(arr);
+                return arr;
+        }
+
+        public void validate(float[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/IntArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces int arrays.
+ */
+public class IntArrayProducer implements GarbageProducer<int[]> {
+        public int[] create(long memory) {
+                int[] arr = new int[Memory.getArrayLength(memory, Memory.getIntSize())];
+                LocalRandom.nextInts(arr);
+                return arr;
+        }
+
+        public void validate(int[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/LongArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces long arrays.
+ */
+public class LongArrayProducer implements GarbageProducer<long[]> {
+        public long[] create(long memory) {
+                long[] arr = new long[Memory.getArrayLength(memory, Memory.getLongSize())];
+                LocalRandom.nextLongs(arr);
+                return arr;
+        }
+
+        public void validate(long[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ObjectArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+
+/**
+ * GarbageProducer implementation that produces object arrays.
+ */
+public class ObjectArrayProducer implements GarbageProducer<Object[]> {
+        public Object[] create(long memory) {
+                return new Object[Memory.getArrayLength(memory, Memory.getObjectExtraSize())];
+        }
+
+        public void validate(Object[] arr) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/array/ShortArrayProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.array;
+
+import nsk.share.test.LocalRandom;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.Memory;
+import nsk.share.TestFailure;
+
+/**
+ * GarbageProducer implementation that produces short arrays.
+ */
+public class ShortArrayProducer implements GarbageProducer<short[]> {
+        public short[] create(long memory) {
+                short[] arr = new short[Memory.getArrayLength(memory, Memory.getShortSize())];
+                LocalRandom.nextShorts(arr);
+                return arr;
+        }
+
+        public void validate(short[] arr) {
+                LocalRandom.validate(arr);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/classload/GeneratedClassProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.classload;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.classload.GeneratingClassLoader;
+import nsk.share.classload.GeneratingClassLoader;
+import nsk.share.gc.gp.GarbageUtils;
+import nsk.share.test.LocalRandom;
+
+/**
+ * Garbage producer that creates classes loaded with GeneratingClassLoader.
+ *
+ * Note: this class is not thread-safe.
+ */
+public class GeneratedClassProducer implements GarbageProducer<Class> {
+        private int number;
+        private String className;
+        private StringBuilder sb = new StringBuilder();
+        private int minPerClassLoader = 50;
+        private int maxPerClassLoader = 150;
+        private int count;
+        private GeneratingClassLoader loader = new GeneratingClassLoader();
+
+        public GeneratedClassProducer() {
+                this(GeneratingClassLoader.DEFAULT_CLASSNAME);
+        }
+
+        public GeneratedClassProducer(String className) {
+                this.className = className;
+        }
+
+        private String getNewName() {
+                sb.delete(0, sb.length());
+                sb.append("Class");
+                sb.append(number);
+                int n = loader.getNameLength() - sb.length();
+                for (int i = 0; i < n; ++i)
+                        sb.append('_');
+                return sb.toString();
+        }
+
+        public Class create(long memory) {
+                try {
+                        if (number++ > maxPerClassLoader || loader == null) {
+                                loader = new GeneratingClassLoader(className);
+                                count = LocalRandom.nextInt(minPerClassLoader, maxPerClassLoader);
+                                number = 0;
+                        }
+                        return loader.loadClass(getNewName());
+                } catch (ClassNotFoundException e) {
+                        throw convertException(e);
+                }
+        }
+
+        public void validate(Class cl) {
+        }
+
+        protected RuntimeException convertException(Exception e) {
+                return new RuntimeException(e);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/list/CircularListProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.list;
+
+import nsk.share.gc.LinkedMemoryObject;
+import nsk.share.gc.Memory;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.MemoryStrategy;
+
+/**
+ * Garbage producer that produces circular linked lists.
+ */
+public class CircularListProducer implements GarbageProducer<LinkedMemoryObject> {
+        private MemoryStrategy memoryStrategy;
+
+        public CircularListProducer(MemoryStrategy memoryStrategy) {
+                this.memoryStrategy = memoryStrategy;
+        }
+
+        public LinkedMemoryObject create(long memory) {
+                long objectSize = memoryStrategy.getSize(memory);
+                int objectCount = memoryStrategy.getCount(memory);
+                return Memory.makeCircularList(objectCount, (int) objectSize);
+        }
+
+        public void validate(LinkedMemoryObject obj) {
+                LinkedMemoryObject o = obj;
+                while (o != null && o != obj)
+                        o = o.getNext();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/list/LinearListProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.list;
+
+import nsk.share.gc.LinkedMemoryObject;
+import nsk.share.gc.Memory;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.MemoryStrategy;
+
+/**
+ * Garbage producer that produces linear linked lists.
+ */
+public class LinearListProducer implements GarbageProducer<LinkedMemoryObject> {
+        private MemoryStrategy memoryStrategy;
+
+        public LinearListProducer(MemoryStrategy memoryStrategy) {
+                this.memoryStrategy = memoryStrategy;
+        }
+
+        public LinkedMemoryObject create(long memory) {
+                long objectSize = memoryStrategy.getSize(memory);
+                int objectCount = memoryStrategy.getCount(memory);
+                return Memory.makeLinearList(objectCount, (int) objectSize);
+        }
+
+        public void validate(LinkedMemoryObject obj) {
+                LinkedMemoryObject o = obj;
+                while (o != null && o != obj)
+                        o = o.getNext();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/HashedGarbageProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.misc;
+
+import nsk.share.gc.gp.DerivedProducer;
+import nsk.share.gc.gp.GarbageProducer;
+
+/*
+ * Garbage producer that also calls {@link java.lang.System#identityHashCode(java.lang.Object)} on produced object.
+ */
+
+/*
+     The description is misleading.  I looked at some old email, and the
+     goal is to stress the code that deals with displaced mark words, so
+     the description should be more like "Stress tests for displaced mark
+     words."  In hotspot, each object has a mark word that stores several
+     things about the object including its hash code (if it has one) and
+     lock state.  Most objects never have a hash code and are never locked,
+     so the mark word is empty.
+
+     Most of our garbage collectors use the mark word temporarily during GC
+     to store a 'forwarding pointer.'  It's not important what that is, but
+     it means that objects that have a hash code or that are locked have to
+     have the mark word saved during GC and then restored at the end of GC.
+     We want to exercise this saving/restoring code.  So a test case should
+     have a large percentage (40-50%) of objects that either have a hash
+     code or are locked.
+
+ */
+public class HashedGarbageProducer<T> extends DerivedProducer<T, T> {
+        public HashedGarbageProducer(GarbageProducer<T> parent) {
+                super(parent);
+        }
+
+        public T create(long memory) {
+                T obj = createParent(memory);
+                System.identityHashCode(obj);
+                return obj;
+        }
+
+        public void validate(T obj) {
+                validateParent(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/TraceProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.misc;
+
+import nsk.share.gc.gp.DerivedProducer;
+import nsk.share.gc.gp.GarbageProducer;
+
+/*
+ * GarbageProducer that traces the production.
+ */
+public class TraceProducer<T> extends DerivedProducer<T, T> {
+        private String prid;
+
+        public TraceProducer(GarbageProducer<T> parent) {
+                super(parent);
+                prid = "Create (" + parent + "): ";
+        }
+
+        public T create(long memory) {
+                T obj = createParent(memory);
+                System.out.println(prid + memory);
+                return obj;
+        }
+
+        public void validate(T obj) {
+                validateParent(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/misc/TwoFieldsObjectProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.gc.gp.misc;
+
+import nsk.share.gc.Memory;
+import nsk.share.gc.*;
+import nsk.share.gc.gp.*;
+
+/**
+ * GarbageProducer that produces object with two fields which
+ * reference objects producer by parent garbage producer.
+ */
+public class TwoFieldsObjectProducer<T> extends DerivedProducer<TwoFieldsObject<T>, T> {
+        public TwoFieldsObjectProducer(GarbageProducer<T> parent) {
+                super(parent);
+        }
+
+        public TwoFieldsObject<T> create(long memory) {
+                long memoryT = (memory - Memory.getObjectExtraSize() - 2 * Memory.getReferenceSize()) / 2;
+                return new TwoFieldsObject<T>(createParent(memoryT), createParent(memoryT));
+        }
+
+        public void validate(TwoFieldsObject<T> obj) {
+                validateParent(obj.getLeft());
+                validateParent(obj.getRight());
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/AllMemoryObjectProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.obj;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.AllMemoryObject;
+
+public class AllMemoryObjectProducer implements GarbageProducer<AllMemoryObject> {
+        public AllMemoryObject create(long memory) {
+                return new AllMemoryObject((int) memory);
+        }
+
+        public void validate(AllMemoryObject obj) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/FinMemoryObject1Producer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.obj;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.FinMemoryObject1;
+
+public class FinMemoryObject1Producer implements GarbageProducer<FinMemoryObject1> {
+        public FinMemoryObject1 create(long memory) {
+                return new FinMemoryObject1((int) memory);
+        }
+
+        public void validate(FinMemoryObject1 obj) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/FinMemoryObjectProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.obj;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.FinMemoryObject;
+
+public class FinMemoryObjectProducer implements GarbageProducer<FinMemoryObject> {
+        public FinMemoryObject create(long memory) {
+                return new FinMemoryObject((int) memory);
+        }
+
+        public void validate(FinMemoryObject obj) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/obj/MemoryObjectProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.obj;
+
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.MemoryObject;
+
+public class MemoryObjectProducer implements GarbageProducer<MemoryObject> {
+        public MemoryObject create(long memory) {
+                return new MemoryObject((int) memory);
+        }
+
+        public void validate(MemoryObject obj) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/InternedStringProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.string;
+
+import nsk.share.gc.gp.DerivedProducer;
+import nsk.share.gc.gp.GarbageProducer;
+
+/**
+ * Garbage producer that creates interned strings.
+ */
+public class InternedStringProducer extends DerivedProducer<String, String> {
+        public InternedStringProducer() {
+                this(new RandomStringProducer());
+        }
+
+        public InternedStringProducer(GarbageProducer<String> parent) {
+                super(parent);
+        }
+
+        public String create(long memory) {
+                return createParent(memory).intern();
+        }
+
+        public void validate(String s) {
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/RandomStringProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.gc.gp.string;
+
+import nsk.share.test.*;
+import nsk.share.gc.Memory;
+import nsk.share.gc.gp.GarbageProducer;
+
+/**
+ * Garbage producer that creates random strings.
+ */
+public class RandomStringProducer implements GarbageProducer<String> {
+
+    private int stringLengthLowerBound = 10;
+
+    public RandomStringProducer() {
+    }
+
+    public RandomStringProducer(int stringLengthLowerBound) {
+        this.stringLengthLowerBound = stringLengthLowerBound;
+    }
+
+    public String create(long memory) {
+        int stringLengthUpperBound = (int) Math.min(memory / 2 - Memory.getObjectExtraSize(), Integer.MAX_VALUE);
+        if (stringLengthUpperBound < stringLengthLowerBound) {
+                stringLengthLowerBound = stringLengthUpperBound;
+        }
+        int length = stringLengthLowerBound + LocalRandom.nextInt(stringLengthUpperBound - stringLengthLowerBound);
+        char[] arr = new char[length];
+        for (int i = 0; i < length; ++i) {
+            arr[i] = (char) LocalRandom.nextInt();
+        }
+        return new String(arr);
+    }
+
+    public void setStringLengthLowerBound(int stringLengthLowerBound) {
+        this.stringLengthLowerBound = stringLengthLowerBound;
+    }
+
+    public void validate(String s) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/string/SimpleStringProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.string;
+
+import nsk.share.test.*;
+import nsk.share.gc.gp.GarbageProducer;
+
+/**
+ * Garbage producer that creates simple strings.
+ */
+public class SimpleStringProducer implements GarbageProducer<String> {
+
+
+    public String create(long memory) {
+        long length = memory/8;
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; ++i)
+            sb.append((char) LocalRandom.nextInt());
+        return sb.toString();
+    }
+
+
+    public void validate(String s) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/gp/tree/NonbranchyTreeProducer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.gp.tree;
+
+import nsk.share.gc.*;
+import nsk.share.gc.gp.*;
+import nsk.share.gc.Memory;
+
+public class NonbranchyTreeProducer implements GarbageProducer<LinkedMemoryObject>, MemoryStrategyAware {
+        private MemoryStrategy memoryStrategy;
+        private float branchiness;
+
+        public NonbranchyTreeProducer(MemoryStrategy memoryStrategy) {
+                this(memoryStrategy, 0.75f);
+        }
+
+        public NonbranchyTreeProducer(MemoryStrategy memoryStrategy, float branchiness) {
+                setMemoryStrategy(memoryStrategy);
+                setBranchiness(branchiness);
+        }
+
+        public LinkedMemoryObject create(long memory) {
+                long objectSize = memoryStrategy.getSize(memory);
+                int objectCount = memoryStrategy.getCount(memory);
+                return Memory.makeNonbranchyTree(objectCount, branchiness, (int) objectSize);
+        }
+
+        public void validate(LinkedMemoryObject obj) {
+        }
+
+        public final void setMemoryStrategy(MemoryStrategy memoryStrategy) {
+                this.memoryStrategy = memoryStrategy;
+        }
+
+        public final void setBranchiness(float branchiness) {
+                this.branchiness = branchiness;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Locker;
+
+/**
+ * CriticalSectionLocker represents a way to lock a resource
+ * by entering some critical section.
+ */
+public abstract class CriticalSectionLocker<T> implements Locker<T> {
+        private transient boolean enabled = false;
+        private transient boolean locked = false;
+        private Object sync = new Object();
+        private Thread thread;
+        private Throwable exception;
+
+        private final Runnable runnable = new Runnable() {
+                public void run() {
+                        //System.out.println("Running");
+                        try {
+                                do {
+                                        synchronized (sync) {
+                                                while (enabled && !locked) {
+                                                        try {
+                                                                sync.wait();
+                                                        } catch (InterruptedException e) {
+                                                        }
+                                                }
+                                                if (!enabled)
+                                                        break;
+                                        }
+                                        do {
+                                                criticalSection();
+                                        } while (locked);
+                                } while (enabled);
+                        //      System.out.println("Exiting");
+                        } catch (RuntimeException t) {
+                                t.printStackTrace();
+                                exception = t;
+                                throw t;
+                        }
+                }
+        };
+
+        public CriticalSectionLocker() {
+        }
+
+        /**
+         * Enter critical section.
+         *
+         */
+        protected abstract void criticalSection();
+
+        public void enable() {
+                synchronized (sync) {
+                        if (enabled)
+                                throw new TestBug("Locker already enabled.");
+//                      System.out.println("Enabling " + this);
+                        enabled = true;
+                        thread = new Thread(runnable, "Locker: " + runnable);
+                        thread.setDaemon(true);
+                        thread.start();
+                }
+        }
+
+        public void lock() {
+                synchronized (sync) {
+                        if (locked)
+                                throw new TestBug("Locker already locked.");
+//                      System.out.println("Locking " + this);
+                        locked = true;
+                        sync.notifyAll();
+                }
+        }
+
+        public void unlock() {
+                synchronized (sync) {
+                        if (!locked)
+                                throw new TestBug("Locker not locked.");
+//                      System.out.println("Unocking " + this);
+                        locked = false;
+                        sync.notifyAll();
+                }
+        }
+
+        public void disable() {
+                synchronized (sync) {
+                        if (!enabled)
+                                throw new TestBug("Locker not enabled.");
+//                      System.out.println("Disabling " + this);
+                        enabled = false;
+                        sync.notifyAll();
+                }
+                try {
+                        thread.join();
+                } catch (InterruptedException e) {
+                        throw new TestBug(e);
+                }
+        }
+
+        public Throwable getException() {
+                return exception;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionObjectLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.TestBug;
+import nsk.share.gc.gp.GarbageProducer;
+import nsk.share.gc.gp.DerivedProducer;
+
+/**
+ * CriticalSectionLocker represents a way to lock
+ * a resource by entering some critical section of
+ * code.
+ */
+public abstract class CriticalSectionObjectLocker<T> extends CriticalSectionTimedLocker<T> implements Locker<T> {
+        public T obj;
+
+        public CriticalSectionObjectLocker(T obj) {
+                this.obj = obj;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/CriticalSectionTimedLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Locker;
+
+/**
+ * CriticalSectionTimedLocker represents a way to lock a resource
+ * by entering some critical section for some time.
+ */
+public abstract class CriticalSectionTimedLocker<T> extends CriticalSectionLocker<T> {
+        private long enterTime;
+        private long sleepTime;
+
+        public CriticalSectionTimedLocker() {
+                this(5000, 10);
+        }
+
+        public CriticalSectionTimedLocker(long enterTime, long sleepTime) {
+                setEnterTime(enterTime);
+                setSleepTime(sleepTime);
+        }
+
+        protected final void criticalSection() {
+                criticalSection(enterTime, sleepTime);
+        }
+
+        /**
+         * Enter critical section for enterTime.
+         *
+         * Usually, something is done in a loop inside this critical section.
+         * In this case, sleepTime is time to sleep after each iteration.
+         */
+        protected abstract void criticalSection(long enterTime, long sleepTime);
+
+        public final void setEnterTime(long enterTime) {
+                this.enterTime = enterTime;
+        }
+
+        public final void setSleepTime(long sleepTime) {
+                this.sleepTime = sleepTime;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/Locker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.gc.gp.GarbageProducer;
+
+/**
+ * Locker represents a way to lock a resource
+ * which may be critical for GC to work.
+ */
+public interface Locker<T> {
+        /**
+         * Enable this locker and make necessary preparations.
+         */
+        public void enable();
+
+        /**
+         * Lock an object.
+         *
+         * There can be multiple calls to this, but to lock
+         * again, one must first unlock.
+         */
+        public void lock();
+
+        /**
+         * Unlock an object.
+         *
+         */
+        public void unlock();
+
+        /**
+         * Get any exceptions that occured.
+         *
+         * @return exception or null if there none
+         */
+        public Throwable getException();
+
+        /**
+         * Disable this locker and make necessary cleanups.
+         */
+        public void disable();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/LockerUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.jni.JNILockers;
+import nsk.share.gc.lock.malloc.MallocLockers;
+import nsk.share.gc.lock.jvmti.JVMTIAllocLockers;
+import nsk.share.gc.lock.jniref.*;
+
+/**
+ * Utility methods for lockers.
+ */
+public class LockerUtils {
+        private LockerUtils() {
+        }
+
+        /**
+         * Obtain Lockers by id.
+         *
+         * @param id identifier of Lockers
+         */
+        public static Lockers getLockers(String id) {
+                if (id == null || id.equals("jni"))
+                        return new JNILockers();
+                else if (id.equals("jniGlobalRef"))
+                        return new JNIGlobalRefLockers();
+                else if (id.equals("jniLocalRef"))
+                        return new JNILocalRefLockers();
+                else if (id.equals("jniRef"))
+                        return new JNIRefLockers();
+                else if (id.equals("jniWeakGlobalRef"))
+                        return new JNIWeakGlobalRefLockers();
+                else if (id.equals("malloc"))
+                        return new MallocLockers();
+                else if (id.equals("jvmtiAlloc"))
+                        return new JVMTIAllocLockers();
+                else
+                        throw new TestBug("Invalid lockers id: " + id);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/Lockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import nsk.share.gc.gp.GarbageProducer;
+
+public interface Lockers<T> {
+        public Locker<T> createLocker(T obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/LockersAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+/**
+ * Marker interface for getting Locker.
+ */
+public interface LockersAware<T> {
+        public void setLockers(Lockers<T> locker);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/MultiLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * MultiLocker is just a locker that uses several lockers.
+ */
+public class MultiLocker<T> implements Locker<T> {
+        private List<Locker<T>> lockers;
+
+        public MultiLocker() {
+                this(new ArrayList<Locker<T>>());
+        }
+
+        public MultiLocker(List<Locker<T>> lockers) {
+                this.lockers = lockers;
+        }
+
+        public void enable() {
+                for (Locker locker : lockers)
+                        locker.enable();
+        }
+
+        public void lock() {
+                for (Locker locker : lockers)
+                        locker.lock();
+        }
+
+        public void unlock() {
+                for (Locker locker : lockers)
+                        locker.unlock();
+        }
+
+        public Throwable getException() {
+                return null;
+        }
+
+        public void disable() {
+                for (Locker locker : lockers)
+                        locker.disable();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_BooleanArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jboolean JNICALL Java_nsk_share_gc_lock_jni_BooleanArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jbooleanArray arr;
+        jboolean *pa;
+        jboolean hash = JNI_TRUE;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return JNI_FALSE;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return JNI_FALSE;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = JNI_FALSE;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/BooleanArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class BooleanArrayCriticalLocker extends CriticalSectionObjectLocker<boolean[]> {
+        private native boolean criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("BooleanArrayCriticalLocker");
+        }
+
+        public BooleanArrayCriticalLocker(boolean[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                boolean javaHash = hashValue(obj);
+                boolean nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private boolean hashValue(boolean[] obj) {
+                boolean hash = true;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_ByteArrayCriticalLocker
+ * Method:    criticalNative
+ */
+JNIEXPORT jbyte JNICALL Java_nsk_share_gc_lock_jni_ByteArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jbyteArray arr;
+        jbyte *pa;
+        jbyte hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return 0;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ByteArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class ByteArrayCriticalLocker extends CriticalSectionObjectLocker<byte[]> {
+        private native byte criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("ByteArrayCriticalLocker");
+        }
+
+        public ByteArrayCriticalLocker(byte[] obj) {
+                super(obj);
+        }
+        protected void criticalSection(long enterTime, long sleepTime) {
+                byte javaHash = hashValue(obj);
+                byte nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+
+        private byte hashValue(byte[] obj) {
+                byte hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_CharArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_CharArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jcharArray arr;
+        jchar *pa;
+        jchar hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        current_time = 0;
+        enterTime /= 1000;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/CharArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class CharArrayCriticalLocker extends CriticalSectionObjectLocker<char[]> {
+        private native char criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("CharArrayCriticalLocker");
+        }
+
+        public CharArrayCriticalLocker(char[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                char javaHash = hashValue(obj);
+                char nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private char hashValue(char[] obj) {
+                char hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_DoubleArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jdouble JNICALL Java_nsk_share_gc_lock_jni_DoubleArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jdoubleArray arr;
+        jdouble *pa;
+        jdouble hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash += pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/DoubleArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class DoubleArrayCriticalLocker extends CriticalSectionObjectLocker<double[]> {
+        private native double criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("DoubleArrayCriticalLocker");
+        }
+
+        public DoubleArrayCriticalLocker(double[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                double javaHash = hashValue(obj);
+                double nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private double hashValue(double[] obj) {
+                double hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash += obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_FloatArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jfloat JNICALL Java_nsk_share_gc_lock_jni_FloatArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jfloatArray arr;
+        jfloat *pa;
+        jfloat hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash += pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/FloatArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class FloatArrayCriticalLocker extends CriticalSectionObjectLocker<float[]> {
+        private native float criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("FloatArrayCriticalLocker");
+        }
+
+        public FloatArrayCriticalLocker(float[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                float javaHash = hashValue(obj);
+                float nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private float hashValue(float[] obj) {
+                float hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash += obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_IntArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jint JNICALL Java_nsk_share_gc_lock_jni_IntArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jintArray arr;
+        jint *pa;
+        jint hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/IntArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class IntArrayCriticalLocker extends CriticalSectionObjectLocker<int[]> {
+        private native int criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("IntArrayCriticalLocker");
+        }
+
+        public IntArrayCriticalLocker(int[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                int javaHash = hashValue(obj);
+                int nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private int hashValue(int[] obj) {
+                int hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/JNILockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JNILockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                if (obj instanceof String)
+                        return new StringCriticalLocker((String) obj);
+                if (obj instanceof boolean[])
+                        return new BooleanArrayCriticalLocker((boolean[]) obj);
+                if (obj instanceof byte[])
+                        return new ByteArrayCriticalLocker((byte[]) obj);
+                if (obj instanceof char[])
+                        return new CharArrayCriticalLocker((char[]) obj);
+                if (obj instanceof double[])
+                        return new DoubleArrayCriticalLocker((double[]) obj);
+                if (obj instanceof float[])
+                        return new FloatArrayCriticalLocker((float[]) obj);
+                if (obj instanceof int[])
+                        return new IntArrayCriticalLocker((int[]) obj);
+                if (obj instanceof long[])
+                        return new LongArrayCriticalLocker((long[]) obj);
+                if (obj instanceof short[])
+                        return new ShortArrayCriticalLocker((short[]) obj);
+                throw new TestBug("Cannot create locker for: " + obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_LongArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jlong JNICALL Java_nsk_share_gc_lock_jni_LongArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jlongArray arr;
+        jlong *pa;
+        jlong hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/LongArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class LongArrayCriticalLocker extends CriticalSectionObjectLocker<long[]> {
+        private native long criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("LongArrayCriticalLocker");
+        }
+
+        public LongArrayCriticalLocker(long[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                long javaHash = hashValue(obj);
+                long nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private long hashValue(long[] obj) {
+                long hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_ShortArrayCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jshort JNICALL Java_nsk_share_gc_lock_jni_ShortArrayCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jshortArray arr;
+        jshort *pa;
+        jshort hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return 0;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return 0;
+                }
+        }
+        arr = (*env)->GetObjectField(env, this, objFieldId);
+        if (arr == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetArrayLength(env, arr);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetPrimitiveArrayCritical(env, arr, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = 0;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleasePrimitiveArrayCritical(env, arr, pa, 0);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, arr);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/ShortArrayCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+public class ShortArrayCriticalLocker extends CriticalSectionObjectLocker<short[]> {
+        private native short criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("ShortArrayCriticalLocker");
+        }
+
+        public ShortArrayCriticalLocker(short[] obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                short javaHash = hashValue(obj);
+                short nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+                        throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+        }
+
+        private short hashValue(short[] obj) {
+                short hash = 0;
+                for (int i = 0; i < obj.length; ++i)
+                        hash ^= obj[i];
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jni_StringCriticalLocker
+ * Method:    criticalNative
+ * Signature: ([Z)Z
+ */
+JNIEXPORT jchar JNICALL Java_nsk_share_gc_lock_jni_StringCriticalLocker_criticalNative
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jsize size, i;
+        jstring str;
+        const jchar *pa;
+        jchar hash = 0;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return JNI_FALSE;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return JNI_FALSE;
+                }
+        }
+        str = (*env)->GetObjectField(env, this, objFieldId);
+        if (str == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return JNI_FALSE;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        size = (*env)->GetStringLength(env, str);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                pa = (*env)->GetStringCritical(env, str, NULL);
+                if (pa != NULL) {
+                        for (i = 0; i < size; ++i)
+                                hash ^= pa[i];
+                } else {
+                        hash = JNI_FALSE;
+                }
+                mssleep((long) sleepTime);
+                (*env)->ReleaseStringCritical(env, str, pa);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, str);
+        return hash;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jni/StringCriticalLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jni;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.gc.gp.string.RandomStringProducer;
+import nsk.share.TestFailure;
+
+public class StringCriticalLocker extends CriticalSectionObjectLocker<String> {
+        private native char criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("StringCriticalLocker");
+        }
+
+        public StringCriticalLocker(String obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+//              System.out.println("Lock: " + s);
+                char javaHash = hashValue(obj);
+                char nativeHash = criticalNative(enterTime, sleepTime);
+                if (nativeHash != 0 && nativeHash != javaHash)
+//                      throw new TestFailure("Native hash: " + nativeHash + " != Java hash: " + javaHash);
+                        throw new TestFailure("Native hash differs from java hash");
+        }
+
+        private char hashValue(String s) {
+                char hash = 0;
+                for (int i = 0; i < s.length(); ++i)
+                        hash ^= s.charAt(i);
+                return hash;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jniref_JNIGlobalRefLocker
+ * Method:    criticalNative
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIGlobalRefLocker_criticalNative
+  (JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jobject obj;
+        jobject gref;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return;
+                }
+        }
+        obj = (*env)->GetObjectField(env, this, objFieldId);
+        if (obj == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                gref = (*env)->NewGlobalRef(env, obj);
+                mssleep((long) sleepTime);
+                (*env)->DeleteGlobalRef(env, gref);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+/**
+ * Locker that uses JNI function NewGlobalRef.
+ */
+public class JNIGlobalRefLocker extends CriticalSectionObjectLocker {
+        private native void criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("JNIGlobalRefLocker");
+        }
+
+        public JNIGlobalRefLocker(Object obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                criticalNative(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIGlobalRefLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JNIGlobalRefLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new JNIGlobalRefLocker(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jniref_JNILocalRefLocker
+ * Method:    criticalNative
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNILocalRefLocker_criticalNative
+  (JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jobject obj;
+        jobject gref;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return;
+                }
+        }
+        obj = (*env)->GetObjectField(env, this, objFieldId);
+        if (obj == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                gref = (*env)->NewLocalRef(env, obj);
+                mssleep((long) sleepTime);
+                (*env)->DeleteLocalRef(env, gref);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+/**
+ * Locker that uses JNI function NewLocalRef.
+ */
+public class JNILocalRefLocker extends CriticalSectionObjectLocker {
+        private native void criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("JNILocalRefLocker");
+        }
+
+        public JNILocalRefLocker(Object obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                criticalNative(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNILocalRefLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JNILocalRefLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new JNILocalRefLocker(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jniref_JNIRefLocker
+ * Method:    criticalNative
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIRefLocker_criticalNative
+  (JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jobject obj;
+        jobject gref, lref, gwref;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return;
+                }
+        }
+        obj = (*env)->GetObjectField(env, this, objFieldId);
+        if (obj == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                gref = (*env)->NewGlobalRef(env, obj);
+                lref = (*env)->NewLocalRef(env, obj);
+                gwref = (*env)->NewWeakGlobalRef(env, obj);
+                mssleep((long) sleepTime);
+                (*env)->DeleteGlobalRef(env, gref);
+                (*env)->DeleteLocalRef(env, lref);
+                (*env)->DeleteWeakGlobalRef(env, gwref);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+/**
+ * JNIRefLocker locks objects using JNI functions
+ * NewGlobalRef, NewLocalRef, NewWeakGlobalRef
+ */
+public class JNIRefLocker extends CriticalSectionObjectLocker {
+        private native void criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("JNIRefLocker");
+        }
+
+        public JNIRefLocker(Object obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                criticalNative(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIRefLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JNIRefLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new JNIRefLocker(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <stdio.h>
+#include <time.h>
+#include "jni_tools.h"
+
+static jfieldID objFieldId = NULL;
+
+/*
+ * Class:     nsk_share_gc_lock_jniref_JNIWeakGlobalRefLocker
+ * Method:    criticalNative
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jniref_JNIWeakGlobalRefLocker_criticalNative
+  (JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        jobject obj;
+        jobject gref;
+        time_t start_time, current_time;
+
+        if (objFieldId == NULL) {
+                jclass class = (*env)->GetObjectClass(env, this);
+                if (class == NULL) {
+                        printf("Error: GetObjectClass returned NULL\n");
+                        return;
+                }
+                objFieldId = (*env)->GetFieldID(env, class, "obj", "Ljava/lang/Object;");
+                if (objFieldId == NULL) {
+                        printf("Error: GetFieldID returned NULL\n");
+                        return;
+                }
+        }
+        obj = (*env)->GetObjectField(env, this, objFieldId);
+        if (obj == NULL) {
+                printf("Error: GetObjectField returned NULL\n");
+                return;
+        }
+        (*env)->SetObjectField(env, this, objFieldId, NULL);
+        start_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - start_time < enterTime) {
+                gref = (*env)->NewWeakGlobalRef(env, obj);
+                mssleep((long) sleepTime);
+                (*env)->DeleteWeakGlobalRef(env, gref);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+        (*env)->SetObjectField(env, this, objFieldId, obj);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.gc.lock.CriticalSectionObjectLocker;
+import nsk.share.TestFailure;
+
+/**
+ * Locker that uses JNI function NewWeakGlobalRef.
+ */
+public class JNIWeakGlobalRefLocker extends CriticalSectionObjectLocker {
+        private native void criticalNative(long enterTime, long sleepTime);
+
+        static {
+                System.loadLibrary("JNIWeakGlobalRefLocker");
+        }
+
+        public JNIWeakGlobalRefLocker(Object obj) {
+                super(obj);
+        }
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                criticalNative(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jniref/JNIWeakGlobalRefLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jniref;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JNIWeakGlobalRefLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new JNIWeakGlobalRefLocker(obj);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <jvmti.h>
+#include <time.h>
+#include <stdlib.h>
+#include "jni_tools.h"
+
+static jvmtiEnv *jvmti = NULL;
+static jvmtiCapabilities caps;
+
+JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+            jint res;
+
+            res = (*jvm)->GetEnv(jvm, (void **) &jvmti, JVMTI_VERSION_1_0);
+            if (res != JNI_OK || jvmti == NULL) {
+                    printf("Wrong result of a valid call to GetEnv!\n");
+                    return JNI_ERR;
+            }
+            return JNI_OK;
+}
+
+/*
+ * Class:     nsk_share_gc_lock_jvmti_JVMTIAllocLocker
+ * Method:    jVMTIAllocSection
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_jvmti_JVMTIAllocLocker_jVMTIAllocSection
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        unsigned char *ptr;
+        time_t current_time, old_time;
+        jvmtiError err;
+        old_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - old_time < enterTime) {
+                err = (*jvmti)->Allocate(jvmti, 1, &ptr);
+                mssleep((long) sleepTime);
+                err = (*jvmti)->Deallocate(jvmti, ptr);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jvmti;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Locker;
+import nsk.share.gc.lock.CriticalSectionTimedLocker;
+
+/**
+ * Malloc locker tries to hold malloc lock (if there is any)
+ * by calling malloc() and free() in a loop.
+ */
+public class JVMTIAllocLocker extends CriticalSectionTimedLocker {
+        static {
+                System.loadLibrary("JVMTIAllocLocker");
+        }
+
+        public JVMTIAllocLocker() {
+        }
+
+        public JVMTIAllocLocker(long enterTime, long sleepTime) {
+                super(enterTime, sleepTime);
+                setSleepTime(sleepTime);
+        }
+
+        /**
+         * This native method does Allocate() / Deallocate() in a loop
+         * while java field locked is set to true, sleeping
+         * for sleepTime between Allocate() and Deallocate() and after
+         * Deallocate().
+         */
+        private native void jVMTIAllocSection(long enterTime, long sleepTime);
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                jVMTIAllocSection(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/jvmti/JVMTIAllocLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.jvmti;
+
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class JVMTIAllocLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new JVMTIAllocLocker();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <jni.h>
+#include <time.h>
+#include <stdlib.h>
+#include "jni_tools.h"
+
+/*
+ * Class:     nsk_share_gc_lock_malloc_MallocLocker
+ * Method:    mallocSection
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_nsk_share_gc_lock_malloc_MallocLocker_mallocSection
+(JNIEnv *env, jobject this, jlong enterTime, jlong sleepTime) {
+        char *ptr;
+        time_t current_time, old_time;
+        old_time = time(NULL);
+        enterTime /= 1000;
+        current_time = 0;
+        while (current_time - old_time < enterTime) {
+                ptr = malloc(1);
+                mssleep((long) sleepTime);
+                free(ptr);
+                mssleep((long) sleepTime);
+                current_time = time(NULL);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.malloc;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Locker;
+import nsk.share.gc.lock.CriticalSectionTimedLocker;
+
+/**
+ * Malloc locker tries to hold malloc lock (if there is any)
+ * by calling malloc() and free() in a loop.
+ */
+public class MallocLocker extends CriticalSectionTimedLocker {
+        static {
+                System.loadLibrary("MallocLocker");
+        }
+
+        public MallocLocker() {
+        }
+
+        public MallocLocker(long enterTime, long sleepTime) {
+                super(enterTime, sleepTime);
+        }
+
+        /**
+         * This native method does malloc() / free() in a loop
+         * while java field locked is set to true, sleeping
+         * for sleepTime between malloc() and free() and after
+         * free().
+         */
+        private native void mallocSection(long enterTime, long sleepTime);
+
+        protected void criticalSection(long enterTime, long sleepTime) {
+                mallocSection(enterTime, sleepTime);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/lock/malloc/MallocLockers.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.lock.malloc;
+
+import nsk.share.TestBug;
+import nsk.share.gc.lock.Lockers;
+import nsk.share.gc.lock.Locker;
+
+public class MallocLockers implements Lockers {
+        public Locker createLocker(Object obj) {
+                return new MallocLocker();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/tree/Tree.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.tree;
+
+public class Tree {
+        private final long nodeSize;
+        private TreeNode root;
+
+        public Tree(long nodeSize) {
+                this.nodeSize = nodeSize;
+                root = new TreeNode(nodeSize);
+        }
+
+        public Tree(TreeNode root) {
+                this.nodeSize = root.getSize();
+                setRoot(root);
+        }
+
+        public TreeNode follow(int path, int depth) {
+                return root.follow(path, depth);
+        }
+
+        public int getHeight() {
+                return root.getHeight();
+        }
+
+        public TreeNode newNode() {
+                return new TreeNode(nodeSize);
+        }
+
+        public final TreeNode getRoot() {
+                return root;
+        }
+
+        public final void setRoot(TreeNode root) {
+                this.root = root;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/tree/TreeNode.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.gc.tree;
+
+import nsk.share.gc.Memory;
+import nsk.share.gc.gp.GarbageProducer;
+
+/**
+ * A node of binary tree.
+ *
+ * A height of subtree defined by this node is kept in the node.
+ * Additionaly, a byte array is used to control how much memory
+ * this node will occupy.
+ */
+public final class TreeNode {
+        private TreeNode left, right;
+        // The height of the tree
+        private int height;
+        private int size;
+        private Object storage;
+
+
+        /**
+         * Create a tree node that will occupy approximately given memory.
+         *
+         * @param memory memory
+         */
+        public TreeNode(long memory) {
+                int length = (int) (memory - (4 * 2 + 2 * Memory.getReferenceSize() + Memory.getObjectExtraSize()));
+                if (length > 0)
+                        storage = new byte[length];
+                size = length;
+        }
+
+        /**
+         * Create a tree node that will occupy approximately given memory.
+         *
+         * @param memory memory
+         */
+        public TreeNode(long size, GarbageProducer gp) {
+                int length = (int) (size - (4 * 2 + 2 * Memory.getReferenceSize() + Memory.getObjectExtraSize()));
+                if (length > 0)
+                        storage = gp.create(length);
+                size = length;
+        }
+        /**
+         * Create a tree node that will occupy approximately given memory
+         * with given left and right children.
+         *
+         * @param memory memory
+         * @param left left child
+         * @param right right child
+         */
+        public TreeNode(long memory, TreeNode left, TreeNode right) {
+                this(memory);
+                setLeft(left);
+                setRight(right);
+                setHeight(1 + Math.max(left == null ? 0 : left.getHeight(), right == null ? 0 : right.getHeight()));
+        }
+
+        /**
+         * Create a tree node that will occupy approximately given memory
+         * with given left and right children.
+         *
+         * @param memory memory
+         * @param left left child
+         * @param right right child
+         */
+        public TreeNode(long memory, GarbageProducer gp, TreeNode left, TreeNode right) {
+                this(memory, gp);
+                setLeft(left);
+                setRight(right);
+                setHeight(1 + Math.max(left == null ? 0 : left.getHeight(), right == null ? 0 : right.getHeight()));
+        }
+
+        /**
+         * Get memory that this node occupies.
+         *
+         * @return memory size
+         */
+        public long getSize() {
+                int length = storage == null ? 0 : size;
+                return length + 4 * 2 + 2 * Memory.getReferenceSize() + Memory.getObjectExtraSize();
+        }
+
+        /**
+         * Get memory that this subtree occupies.
+         *
+         * @return memory size
+         */
+        public long getTotalSize() {
+                long memory = getSize();
+                if (left != null)
+                        memory += left.getSize();
+                if (right != null)
+                        memory += right.getSize();
+                return memory;
+        }
+
+        /**
+         * Follow path determined by bits given integer and depth.
+         *
+         * @param path path encoded in integer
+         * @param depth depth to follow
+         * @return end of the path
+         */
+        public TreeNode follow(int path, int depth) {
+                if (depth == 0)
+                        return this;
+                TreeNode current = this;
+                TreeNode prev = null;
+                for (int i = 0; i < depth; ++i) {
+                        prev = current;
+                        if ((path & 1) == 0)
+                                current = current.left;
+                        else
+                                current = current.right;
+                        path >>= 1;
+                }
+                return prev;
+        }
+
+        /**
+         * Swap left child of this node with left child of another node.
+         *
+         * @param another another node
+         */
+        public void swapLeft(TreeNode another) {
+                TreeNode tmp = another.left;
+                another.left = left;
+                left = tmp;
+        }
+        /**
+         * Swap right child of this node with right child of another node.
+         *
+         * @param another another node
+         */
+        public void swapRight(TreeNode another) {
+                TreeNode tmp = another.right;
+                another.right = right;
+                right = tmp;
+        }
+
+        public final TreeNode getLeft() {
+                return left;
+        }
+
+        public final void setLeft(TreeNode left) {
+                this.left = left;
+        }
+
+        public final TreeNode getRight() {
+                return right;
+        }
+
+        public final void setRight(TreeNode right) {
+                this.right = right;
+        }
+
+        public final int getHeight() {
+                return height;
+        }
+
+        public boolean hasLeft() {
+                return left != null;
+        }
+
+        public boolean hasRight() {
+                return right != null;
+        }
+
+        /**
+         * Get actual height of the tree.
+         */
+        public int getActualHeight() {
+                return 1 + Math.max(left == null ? 0 : left.getActualHeight(), right == null ? 0 : right.getActualHeight());
+        }
+
+        /**
+         * Get lenght of shortest path from root to leaf in the tree.
+         */
+        public int getShortestPath() {
+                return 1 + Math.min(left == null ? 0 : left.getActualHeight(), right == null ? 0 : right.getActualHeight());
+        }
+
+        public final void setHeight(int value) {
+                this.height = value;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/AbstractJDIDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import nsk.share.jpda.*;
+
+public class AbstractJDIDebuggee extends AbstractDebuggeeTest {
+
+    /*
+     * Create argument handler handling options specific for JDI tests
+     */
+    protected DebugeeArgumentHandler createArgumentHandler(String args[]) {
+        return new ArgumentHandler(args);
+    }
+
+    public static void main(String args[]) {
+        AbstractJDIDebuggee debuggee = new AbstractJDIDebuggee();
+        debuggee.init(args);
+        debuggee.doTest();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ArgumentHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import nsk.share.*;
+import nsk.share.jpda.*;
+
+import com.sun.jdi.VirtualMachine;
+
+/**
+ * Parser for JDI test's specific command-line arguments.
+ * <p>
+ * <code>ArgumentHandler</code> handles JDI test's specific
+ * arguments related to launching debugee VM using JDI features
+ * in addition to general arguments recognized by
+ * <code>DebugeeArgumentHandler</code> and <code>ArgumentParser</code>.
+ * <p>
+ * Following is the list of specific options recognized by
+ * <code>AgrumentHandler</code>:
+ * <ul>
+ * <li> <code>-connector=[launching|attaching|listening|default]</code> -
+ *   JDI connector type
+ * <li> <code>-transport=[socket|shmem|default]</code> -
+ *   JDWP transport kind
+ * <li> <code>-jdi.trace=[none|all|events|sends|receives|reftypes|objrefs]</code> -
+ *   JDI trace mode for debugee VM
+ * </ul>
+ * <p>
+ * See also list of arguments recognized by the base <code>DebugeeArgumentHandler</code>
+ * and <code>ArgumentParser</code> classes.
+ * <p>
+ * See also description of <code>ArgumentParser</code> how to work with
+ * command line arguments and options.
+ *
+ * @see ArgumentParser
+ * @see DebugeeArgumentHandler
+ */
+public class ArgumentHandler extends DebugeeArgumentHandler {
+
+    static private String JDI_CONNECTOR_NAME_PREFIX = "com.sun.jdi.";
+
+    /**
+     * Keep a copy of raw command-line arguments and parse them;
+     * but throw an exception on parsing error.
+     *
+     * @param  args  Array of the raw command-line arguments.
+     *
+     * @throws  NullPointerException  If <code>args==null</code>.
+     * @throws  IllegalArgumentException  If Binder or Log options
+     *                                    are set incorrectly.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public ArgumentHandler(String args[]) {
+        super(args);
+//        parseArguments();
+    }
+
+    /**
+     * Overriden method returns transport type for JDWP connection, specified by
+     * <code>-transport</code> command line option, or <i>"default"</i> value
+     * by default.
+     *
+     * @see #getTransportName()
+     * @see #isSocketTransport()
+     * @see #isShmemTransport()
+     * @see #isDefaultTransport()
+     * @see #setRawArguments(String[])
+     */
+    public String getTransportType() {
+        return options.getProperty("transport", "default");
+    }
+
+    /**
+     * Overriden method returns <i>true</i> if <code>socket</code> transport
+     * is used either as specified or as a platform default transport.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isSocketTransport() {
+        String transport = getTransportType();
+        if (transport.equals("socket"))
+            return true;
+        if (transport.equals("shmem"))
+            return false;
+        if (transport.equals("default")) {
+            String arch = getArch();
+            if (arch == null)
+                if (System.getProperty("os.arch").equals("windows-i586"))
+                    return false;
+                else
+                    return true;
+            else if (arch.equals("windows-i586"))
+                return false;
+            else
+                return true;
+        }
+        throw new TestBug("Bad value of argument transport: " + transport);
+    }
+
+    /**
+     * Overriden method returns <i>true</i> if <code>shmem</code> transport is used
+     * either as specified or as a platform default transport.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isShmemTransport() {
+        return ! isSocketTransport();
+    }
+
+    /**
+     * Overriden method returns <i>true</i> if transport type is <code>default</code>.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isDefaultTransport() {
+        String transport = getTransportType();
+        return transport.equals("default");
+    }
+
+    /**
+     * Overriden methos returns JDI connector type, specified by
+     * <code>-connector</code>. or <i>"default"</i> value by default.
+     *
+     * @see #getConnectorName()
+     * @see #isLaunchingConnector()
+     * @see #isAttachingConnector()
+     * @see #isListeningConnector()
+     * @see #isDefaultConnector()
+     * @see #setRawArguments(String[])
+     */
+    public String getConnectorType() {
+        return options.getProperty("connector", "default");
+    }
+
+    /**
+     * Overriden method returns full connector name corresponding to
+     * the used connector and transport types.
+     *
+     * @see #getConnectorType()
+     * @see #getTransportType()
+     */
+    public String getConnectorName() {
+        if (isLaunchingConnector()) {
+            if (isRawLaunchingConnector())
+                return JDI_CONNECTOR_NAME_PREFIX + "RawCommandLineLaunch";
+            return JDI_CONNECTOR_NAME_PREFIX + "CommandLineLaunch";
+        }
+        if (isAttachingConnector()) {
+            if (isSocketTransport())
+                return JDI_CONNECTOR_NAME_PREFIX + "SocketAttach";
+            if (isShmemTransport())
+                return JDI_CONNECTOR_NAME_PREFIX + "SharedMemoryAttach";
+            return JDI_CONNECTOR_NAME_PREFIX + "SocketAttach";
+        }
+        if (isListeningConnector()) {
+            if (isSocketTransport())
+                return JDI_CONNECTOR_NAME_PREFIX + "SocketListen";
+            if (isShmemTransport())
+                return JDI_CONNECTOR_NAME_PREFIX + "SharedMemoryListen";
+            return JDI_CONNECTOR_NAME_PREFIX + "SocketListen";
+        }
+        throw new Failure("Unable to find full name of connector \"" + getConnectorType()
+                        + "\" for transport \"" + getTransportType() + "\"");
+    }
+
+    /**
+     * Overriden method returns <i>true</i> if connector type is <code>default</code>.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isDefaultConnector() {
+        return getConnectorType().equals("default");
+    }
+
+    /**
+     * Return <i>true</i> if connector type is <code>launching</code>
+     * <code>rawlaunching<code> or <code>default</code>.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isLaunchingConnector() {
+        return getConnectorType().equals("launching")
+                || getConnectorType().equals("rawlaunching")
+                || getConnectorType().equals("default");
+    }
+
+    /**
+     * Return <i>true</i> if connector type is <code>rawlaunching</code>.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isRawLaunchingConnector() {
+        return getConnectorType().equals("rawlaunching");
+    }
+
+    /**
+     * Return string representation of debug trace mode, specified by
+     * <code>-jdi.trace</code> command line option, or <i>"none"</i>
+     * value by default.
+     * <p>
+     * Possible values for this option are the same as symbolic constants names
+     * in <code>com.sun.jdi.VirtualMachine</code> interface:
+     * <br>&nbsp;&nbsp;<code>"all"</code>, or
+     * <br>&nbsp;&nbsp;<code>"events"</code>, or
+     * <br>&nbsp;&nbsp;<code>"none"</code>, or
+     * <br>&nbsp;&nbsp;<code>"objrefs"</code>, or
+     * <br>&nbsp;&nbsp;<code>"receives"</code>, or
+     * <br>&nbsp;&nbsp;<code>"reftypes"</code>, or
+     * <br>&nbsp;&nbsp;<code>"sends"</code>.
+     *
+     * @see #getTraceMode()
+     * @see #setRawArguments(String[])
+     */
+    public String getTraceModeString() {
+        return options.getProperty("jdi.trace", "none");
+    }
+
+    /**
+     * Return integer code corresponding to debug trace mode, specified by
+     * <code>-jdi.trace</code> command line option, or <i>VirtualMachine.TRACE_NONE</i>
+     * value by default.
+     * <p>
+     * Possible values are the same as symbolic constant values
+     * in <code>com.sun.jdi.VirtualMachine</code> interface:
+     * <ul>
+     *   <li><code>VirtualMachine.TRACE_ALL</code>
+     *   <li><code>VirtualMachine.TRACE_EVENTS</code>
+     *   <li><code>VirtualMachine.TRACE_NONE</code>
+     *   <li><code>VirtualMachine.TRACE_OBJREFS</code>
+     *   <li><code>VirtualMachine.TRACE_RECEIVES</code>
+     *   <li><code>VirtualMachine.TRACE_REFTYPES</code>
+     *   <li><code>VirtualMachine.TRACE_SENDS</code>
+     * </ul>
+     *
+     * @see #getTraceModeString()
+     * @see #setRawArguments(String[])
+     */
+    public int getTraceMode() {
+        String val = getTraceModeString();
+        if (val == null)
+            return VirtualMachine.TRACE_NONE;
+        if (val.equals("none"))
+            return VirtualMachine.TRACE_NONE;
+        if (val.equals("all"))
+            return VirtualMachine.TRACE_ALL;
+        if (val.equals("events"))
+            return VirtualMachine.TRACE_EVENTS;
+        if (val.equals("objrefs"))
+            return VirtualMachine.TRACE_OBJREFS;
+        if (val.equals("receives"))
+            return VirtualMachine.TRACE_RECEIVES;
+        if (val.equals("reftypes"))
+            return VirtualMachine.TRACE_REFTYPES;
+        if (val.equals("sends"))
+            return VirtualMachine.TRACE_SENDS;
+        throw new TestBug("Unknown JDI trace mode string: " + val);
+    }
+
+    // delay between connection attempts, used in connectors tests
+    public int getConnectionDelay() {
+        String value = options.getProperty("connectionDelay", "4000");
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not integer value of \"connectionDelay\" argument: " + value);
+        }
+    }
+
+
+    /**
+     * Return <i>true</i> if the test should pass in any case i.e.
+     * an entity specified by the arguments <code>entry[]</code> is
+     * not implemented on the tested platform. Name of the tested
+     * platform is resolved from the "<code>-arch</code>" option.
+     *
+     * @param  entry   Array with the arguments which are specifing
+     * the entity.
+     *
+     * @throws Oddity  If test parameter<code>-arch</code>
+     *                 has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean shouldPass(String entry[]) {
+        String arch;
+        boolean found = false;
+
+        if ((arch=getArch()) == null)
+            throw new Oddity("Test parameter -arch should be set");
+
+        for (int i=0; i < CheckedFeatures.notImplemented.length; i++) {
+            if (CheckedFeatures.notImplemented[i][0].equals(arch) &&
+                CheckedFeatures.notImplemented[i].length == (entry.length+1)) {
+                for (int j=1; j < (entry.length+1); j++) {
+                    if (CheckedFeatures.notImplemented[i][j].equals(entry[j-1]))
+                        found = true;
+                    else {
+                        found = false;
+                        break;
+                    }
+                }
+                if (found) return true; // the entry[] is not implemented
+            }
+        }
+
+        return false; // the entry[] is implemented
+    }
+
+    /**
+     * Return <i>true</i> if the test should pass in any case i.e.
+     * an entity specified by the argument <code>entry</code> is
+     * not implemented on the tested platform. Name of the tested
+     * platform is resolved from the "<code>-arch</code>" option.
+     *
+     * @param  entry   String with the argument which is specifing
+     * the entity.
+     *
+     * @throws Oddity  If test parameter<code>-arch</code>
+     *                 has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean shouldPass(String entry) {
+        return (shouldPass(new String[] {entry}));
+    }
+
+    /**
+     * Return <i>true</i> if the test should pass in any case i.e.
+     * an entity specified by the arguments <code>entry1</code> and
+     * <code>entry2</code> is not implemented on the tested platform.
+     * The entry is considered to be not implemented if exact entry
+     *  "entry1, entry2" or its main entry "entry1" is not implemented.
+     *
+     * Name of the tested platform is resolved from the "<code>-arch</code>"
+     * option.
+     *
+     * @param  entry1   String with the argument 1 which is specifing
+     * the entity.
+     *
+     * @param  entry2   String with the argument 2 which is specifing
+     * the entity.
+     *
+     * @throws Oddity  If test parameter<code>-arch</code>
+     *                 has not been set.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean shouldPass(String entry1, String entry2) {
+        return ( shouldPass(new String[] {entry1, entry2}) ||
+                 shouldPass(new String[] {entry1})  );
+    }
+
+    /**
+     * Check if an option is admissible and has proper value.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @param option option name
+     * @param value string representation of value (could be an empty string)
+     *              null if this option has no value
+     * @return <i>true</i> if option is admissible and has proper value
+     *         <i>false</i> if otion is not admissible
+     *
+     * @throws <i>BadOption</i> if option has illegal value
+     *
+     * @see #parseArguments()
+     */
+    protected boolean checkOption(String option, String value) {
+
+        // check options with enumerated values
+
+        if (option.equals("connectionDelay")) {
+            try {
+                int number = Integer.parseInt(value);
+                if (number <= 0) {
+                    throw new BadOption(option + ": must be a positive integer");
+                }
+            } catch (NumberFormatException e) {
+                throw new BadOption(option + ": must be an integer");
+            }
+
+            return true;
+        }
+
+        if (option.equals("connector")) {
+            if ((!value.equals("launching"))
+                && (!value.equals("rawlaunching"))
+                && (!value.equals("attaching"))
+                && (!value.equals("listening"))
+                && (!value.equals("default"))) {
+                throw new BadOption(option + ": value must be one of: "
+                                           + "launching, attaching, listening, default");
+            }
+            return true;
+        }
+
+        if (option.equals("transport")) {
+            if ((!value.equals("socket"))
+                && (!value.equals("shmem"))
+                && (!value.equals("default"))) {
+                throw new BadOption(option + ": must be one of: "
+                                           + "socket, shmem, default");
+            }
+            return true;
+        }
+
+        if (option.equals("jdi.trace")) {
+            if ((!value.equals("all"))
+                && (!value.equals("none"))
+                && (!value.equals("events"))
+                && (!value.equals("receives"))
+                && (!value.equals("sends"))
+                && (!value.equals("reftypes"))
+                && (!value.equals("objrefs"))) {
+                throw new BadOption(option + ": value must be one of: "
+                                           + "none, all, events, receives, sends, reftypes, objrefs");
+            }
+            return true;
+        }
+
+        return super.checkOption(option, value);
+    }
+
+    /**
+     * Check options against inconcistence.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @see #parseArguments()
+     */
+    protected void checkOptions() {
+/*
+        if (isTransportAddressDynamic() &&
+                (!isDefaultConnector() && isRawLaunchingConnector())) {
+            throw new BadOption("-transport.address=dynamic should NOT be used with"
+                                + " -connector=rawlaunching");
+        }
+ */
+
+        if (! isLaunchedLocally() && ! isDefaultDebugeeSuspendMode()) {
+            throw new BadOption("inconsistent options: "
+                                + "-debugee.launch=" + getLaunchMode()
+                                + " and -debugee.suspend=" + getDebugeeSuspendMode());
+        }
+
+        if (! isLaunchedLocally() && isLaunchingConnector()) {
+            throw new BadOption("inconsistent options: "
+                                + "-debugee.launch=" + getLaunchMode()
+                                + " and -connector=" + getConnectorType());
+        }
+
+        if (isLaunchingConnector() && ! isDefaultTransport()) {
+            throw new BadOption("inconsistent options: "
+                                + "-connector=" + getConnectorType()
+                                + " and -transport=" + getTransportType());
+        }
+
+        if (! isLaunchingConnector() && isDefaultTransport()) {
+            throw new BadOption("inconsistent options: "
+                                + "-connector=" + getConnectorType()
+                                + " and -transport=" + getTransportType());
+        }
+
+        if (! isDefaultJVMDIStrictMode()) {
+            throw new BadOption("unsupported options: "
+                                + "jvmdi.strict: non default JVMDI strict mode is not supported now" + getJVMDIStrictMode());
+        }
+
+/*
+        if (! isLaunchedLocally() && ! isDefaultJVMDIStrictMode()) {
+            throw new BadOption("inconsistent options: "
+                                + "-launch.mode=" + getLaunchMode()
+                                + " and -jvmdi.strict=" + getJVMDIStrictMode());
+        }
+ */
+
+        super.checkOptions();
+    }
+}
+
+/**
+ * This is an auxiliary class intended for <code>ArgumentHandler</code>.
+ * The following information is used by the <code>ArgumentHandler</code>
+ * for resolving features (i.e., JDI connectors and transport names)
+ * which are not implemented on given platform (the first column).
+ * This list is actual for JDK 1.3.x, 1.4.x, 1.5.0, 1.6.0.
+ *
+ * @see ArgumentHandler
+ */
+class CheckedFeatures {
+
+    static final String[][] notImplemented = {
+
+            // attaching connectors
+        /*
+         * From docs/technotes/guides/jpda/conninv.html:
+         * "
+         *  This connector can be used by a debugger application to attach to
+         *  a currently running target VM through the shared memory transport. It is
+         *  available only on the Microsoft Windows platform.
+         *  "
+         */
+        {"solaris-sparc",   "com.sun.jdi.SharedMemoryAttach"},
+        {"solaris-sparcv9", "com.sun.jdi.SharedMemoryAttach"},
+        {"solaris-i586",    "com.sun.jdi.SharedMemoryAttach"},
+        {"solaris-amd64",   "com.sun.jdi.SharedMemoryAttach"},
+        {"solaris-x64",     "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-i586",      "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-ia64",      "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-amd64",     "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-x64",       "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-sparc",     "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-sparcv9",   "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-aarch64",   "com.sun.jdi.SharedMemoryAttach"},
+        {"linux-arm",       "com.sun.jdi.SharedMemoryAttach"},
+        {"macosx-amd64",    "com.sun.jdi.SharedMemoryAttach"},
+        {"mac-x64",         "com.sun.jdi.SharedMemoryAttach"},
+
+            // listening connectors
+        /*
+         * From docs/technotes/guides/jpda/conninv.html:
+         * "
+         *  This connector can be used by a debugger application to accept a
+         *  connection from  a separately invoked target VM through the shared memory
+         *  transport.
+         *  It is available only on the Microsoft Windows platform.
+         *  "
+         */
+        {"solaris-sparc",   "com.sun.jdi.SharedMemoryListen"},
+        {"solaris-sparcv9", "com.sun.jdi.SharedMemoryListen"},
+        {"solaris-i586",    "com.sun.jdi.SharedMemoryListen"},
+        {"solaris-amd64",   "com.sun.jdi.SharedMemoryListen"},
+        {"solaris-x64",     "com.sun.jdi.SharedMemoryListen"},
+        {"linux-i586",      "com.sun.jdi.SharedMemoryListen"},
+        {"linux-ia64",      "com.sun.jdi.SharedMemoryListen"},
+        {"linux-amd64",     "com.sun.jdi.SharedMemoryListen"},
+        {"linux-x64",       "com.sun.jdi.SharedMemoryListen"},
+        {"linux-sparc",     "com.sun.jdi.SharedMemoryListen"},
+        {"linux-sparcv9",   "com.sun.jdi.SharedMemoryListen"},
+        {"linux-aarch64",   "com.sun.jdi.SharedMemoryListen"},
+        {"linux-arm",       "com.sun.jdi.SharedMemoryListen"},
+        {"macosx-amd64",    "com.sun.jdi.SharedMemoryListen"},
+        {"mac-x64",         "com.sun.jdi.SharedMemoryListen"},
+
+            // launching connectors
+        /*
+         * From docs/technotes/guides/jpda/conninv.html:
+         * "
+         *  Sun Command Line Launching Connector
+         *  This connector can be used by a debugger application to launch a
+         *  Sun VM or any other VM which supports the same invocation options with
+         *  respect to debugging. The details of launching the VM and specifying the
+         *  necessary debug options are handled by the connector. The underlying
+         *  transport used by this connector depends on the platform. On Microsoft
+         *  Windows, the shared memory transport is used. On Solaris and Linux the
+         *  socket transport is used.
+         * "
+         */
+        {"solaris-sparc",   "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"solaris-sparc",   "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"solaris-sparcv9", "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"solaris-sparcv9", "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"solaris-i586",    "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"solaris-i586",    "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"solaris-amd64",   "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"solaris-amd64",   "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"solaris-x64",     "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"solaris-x64",     "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-i586",      "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-i586",      "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-ia64",      "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-ia64",      "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-amd64",     "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-amd64",     "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-x64",       "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-x64",       "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-sparc",     "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-sparc",     "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-sparcv9",   "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-sparcv9",   "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-aarch64",   "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-aarch64",   "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"linux-arm",       "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"linux-arm",       "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"windows-i586",    "com.sun.jdi.CommandLineLaunch", "dt_socket"},
+        {"windows-i586",    "com.sun.jdi.RawCommandLineLaunch", "dt_socket"},
+
+        {"windows-ia64",    "com.sun.jdi.CommandLineLaunch", "dt_socket"},
+        {"windows-ia64",    "com.sun.jdi.RawCommandLineLaunch", "dt_socket"},
+
+        {"windows-amd64",   "com.sun.jdi.CommandLineLaunch", "dt_socket"},
+        {"windows-amd64",   "com.sun.jdi.RawCommandLineLaunch", "dt_socket"},
+
+        {"windows-x64",     "com.sun.jdi.CommandLineLaunch", "dt_socket"},
+        {"windows-x64",     "com.sun.jdi.RawCommandLineLaunch", "dt_socket"},
+
+        {"macosx-amd64",     "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"macosx-amd64",     "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        {"mac-x64",         "com.sun.jdi.CommandLineLaunch", "dt_shmem"},
+        {"mac-x64",         "com.sun.jdi.RawCommandLineLaunch", "dt_shmem"},
+
+        // shared memory transport is implemented only on windows platform
+        {"solaris-sparc",   "dt_shmem"},
+        {"solaris-sparcv9", "dt_shmem"},
+        {"solaris-i586",    "dt_shmem"},
+        {"solaris-amd64",   "dt_shmem"},
+        {"solaris-x64",     "dt_shmem"},
+        {"linux-i586",      "dt_shmem"},
+        {"linux-ia64",      "dt_shmem"},
+        {"linux-amd64",     "dt_shmem"},
+        {"linux-x64",       "dt_shmem"},
+        {"linux-sparc",     "dt_shmem"},
+        {"linux-sparcv9",   "dt_shmem"},
+        {"linux-aarch64",   "dt_shmem"},
+        {"linux-arm",       "dt_shmem"},
+        {"macosx-amd64",    "dt_shmem"},
+        {"mac-x64",         "dt_shmem"},
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Binder.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,1273 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import nsk.share.*;
+import nsk.share.jpda.*;
+
+import com.sun.jdi.*;
+import com.sun.jdi.connect.*;
+
+import com.sun.jdi.connect.Connector.Argument;
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * This class provides debugger with connection to debugee VM
+ * using JDI connectors.
+ *<p>
+ * This class provides abilities to launch and bind to debugee VM
+ * as described for base <code>DebugeeBinder</code> class,
+ * using JDI connectors and <code>com.sun.VirtualMachine</code> mirror.
+ * <p>
+ * When <code>Binder</code> is asked to bind to debugee by invoking
+ * <code>bindToBebugee()</code> method it uses
+ * <code>com.sun.jdi.Connector</code> object corresponding to
+ * value of command line options <code>-connector</code> and
+ * <code>-transport</code> to launch and connect to debugee VM.
+ * After debugee is launched and connection is established
+ * <code>Binder</code> uses <code>com.sun.jdi.VirtualMachine</code>
+ * object to construct <code>Debugee</code> object, that
+ * provides abilities to interact with debugee VM.
+ *
+ * @see Debugee
+ * @see DebugeeBinder
+ */
+public class Binder extends DebugeeBinder {
+
+    /**
+     * Default message prefix for <code>Binder</code> object.
+     */
+    public static final String LOG_PREFIX = "binder> ";
+
+    /**
+     * Get version string.
+     */
+    public static String getVersion () {
+        return "@(#)Binder.java 1.14 03/10/08";
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Handler of command line arguments.
+     */
+    private ArgumentHandler argumentHandler = null;
+
+    /**
+     * Return <code>argumentHandler</code> of this binder.
+     */
+    public ArgumentHandler getArgumentHandler() {
+        return argumentHandler;
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Make <code>Binder</code> object and pass raw command line arguments.
+     *
+     * @deprecated  Use newer
+     *              <code>Binder(ArgumentHandler,Log)</code>
+     *              constructor.
+     */
+    public Binder (String args[]) {
+        this(args, new Log(System.err));
+    }
+
+    /**
+     * Make <code>Binder</code> object for raw command line arguments
+     * and specified <code>log</code> object.
+     *
+     * @deprecated  Use newer
+     *              <code>Binder(ArgumentHandler,Log)</code>
+     *              constructor.
+     */
+    public Binder (String args[], Log log) {
+        this(new ArgumentHandler(args), log);
+    }
+
+    /**
+     * Make <code>Binder</code> object for specified command line arguments
+     * and <code>log</code> object.
+     */
+    public Binder (ArgumentHandler argumentHandler, Log log) {
+        super(argumentHandler, log);
+        this.argumentHandler = argumentHandler;
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Make initial <code>Debugee</code> object for local debuggee process
+     * started with launching connector.
+     */
+    public Debugee makeLocalDebugee(Process process) {
+        LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(process, this);
+
+        Finalizer finalizer = new Finalizer(debugee);
+        finalizer.activate();
+
+        return debugee;
+    }
+
+    /**
+     * Launch local debuggee process with specified command line
+     * and make initial <code>Debugee</code> object.
+     */
+    public Debugee startLocalDebugee(String cmd) {
+        Process process = null;
+
+        try {
+            process = launchProcess(cmd);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching local debuggee VM process:\n\t"
+                            + e);
+        }
+
+        return makeLocalDebugee(process);
+    }
+
+    /**
+     * Make debuggee wrapper for already launched debuggee VM.
+     * After enwraping debugee's output is redirected to Binder's log,
+     * VMStartEvent is received and debuggee is initialized.
+     */
+    public Debugee enwrapDebugee(VirtualMachine vm, Process proc) {
+        Debugee debugee = makeLocalDebugee(proc);
+
+        display("Redirecting VM output");
+        debugee.redirectOutput(log);
+        debugee.setupVM(vm);
+
+        long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds
+
+        display("Waiting for VM initialized");
+        debugee.waitForVMInit(timeout);
+
+        return debugee;
+    }
+
+    /**
+     * Launch debugee VM and establish connection to it without waiting for VMStartEvent.
+     * After launching debugee's output is redirected to Binder's log,
+     * but VMStartEvent is not received and so debuggee is not fully initialized.
+     *
+     * @see #bindToDebugee(String)
+     */
+    public Debugee bindToDebugeeNoWait(String classToExecute) {
+
+        VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
+        display("VirtualMachineManager: version "
+                + vmm.majorInterfaceVersion() + "."
+                + vmm.minorInterfaceVersion());
+
+        Debugee debugee = null;
+
+        String classPath = null;
+//        classPath = System.getProperty("java.class.path");
+
+        prepareForPipeConnection(argumentHandler);
+
+        if (argumentHandler.isLaunchedLocally()) {
+
+            if (argumentHandler.isDefaultConnector()) {
+                debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isRawLaunchingConnector()) {
+                debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isLaunchingConnector()) {
+                debugee = localLaunchDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isAttachingConnector()) {
+                debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isLaunchingConnector()) {
+                debugee = localLaunchDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isListeningConnector()) {
+                debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
+            } else {
+                throw new TestBug("Unexpected connector type for local debugee launch mode"
+                                  + argumentHandler.getConnectorType());
+            }
+
+        } else if (argumentHandler.isLaunchedRemotely()) {
+
+            connectToBindServer(classToExecute);
+
+            if (argumentHandler.isAttachingConnector()) {
+                debugee = remoteLaunchAndAttachDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isListeningConnector()) {
+                debugee = remoteLaunchAndListenDebugee(vmm, classToExecute, classPath);
+            } else {
+                throw new TestBug("Unexpected connector type for remote debugee launch mode"
+                                  + argumentHandler.getConnectorType());
+            }
+
+        } else if (argumentHandler.isLaunchedManually()) {
+
+            if (argumentHandler.isAttachingConnector()) {
+                debugee = manualLaunchAndAttachDebugee(vmm, classToExecute, classPath);
+            } else if (argumentHandler.isListeningConnector()) {
+                debugee = manualLaunchAndListenDebugee(vmm, classToExecute, classPath);
+            } else {
+                throw new TestBug("Unexpected connector type for manual debugee launch mode"
+                                  + argumentHandler.getConnectorType());
+            }
+
+        } else {
+            throw new Failure("Unexpected debugee launching mode: " + argumentHandler.getLaunchMode());
+        }
+
+        return debugee;
+    }
+
+    /**
+     * Launch debugee VM and establish JDI connection.
+     * After launching debugee's output is redirected to Binder's log,
+     * VMStart event is received and debuggee is initialized.
+     *
+     * @see #bindToDebugeeNoWait(String)
+     */
+    public Debugee bindToDebugee(String classToExecute) {
+        Debugee debugee = bindToDebugeeNoWait(classToExecute);
+
+        if(argumentHandler.getOptions().getProperty("traceAll") != null)
+            debugee.VM().setDebugTraceMode(VirtualMachine.TRACE_ALL);
+
+        long timeout = argumentHandler.getWaitTime() * 60 * 1000; // milliseconds
+
+        display("Waiting for VM initialized");
+        debugee.waitForVMInit(timeout);
+
+        return debugee;
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Launch debugee locally via the default LaunchingConnector.
+     */
+    private Debugee localDefaultLaunchDebugee (VirtualMachineManager vmm,
+                                                String classToExecute,
+                                                String classPath) {
+        display("Finding connector: " + "default" );
+        LaunchingConnector connector = vmm.defaultConnector();
+        Map<String,? extends Argument> arguments = setupLaunchingConnector(connector, classToExecute, classPath);
+
+        VirtualMachine vm;
+        try {
+            display("Launching debugee");
+            vm = connector.launch(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
+        } catch (VMStartException e) {
+            e.printStackTrace(log.getOutStream());
+            String msg = readVMStartExceptionOutput(e, log.getOutStream());
+            throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\n" + msg);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
+        };
+
+        Process process = vm.process();
+        Debugee debugee = makeLocalDebugee(process);
+        debugee.redirectOutput(log);
+        debugee.setupVM(vm);
+
+        return debugee;
+    }
+
+
+    /**
+     * Launch debugee locally via the default LaunchingConnector.
+     */
+    private Debugee localLaunchDebugee (VirtualMachineManager vmm,
+                                            String classToExecute,
+                                            String classPath) {
+
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        LaunchingConnector connector =
+            (LaunchingConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.launchingConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupLaunchingConnector(connector, classToExecute, classPath);
+
+        VirtualMachine vm;
+        try {
+            display("Launching debugee");
+            vm = connector.launch(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
+        } catch (VMStartException e) {
+            e.printStackTrace(log.getOutStream());
+            String msg = readVMStartExceptionOutput(e, log.getOutStream());
+            throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\nProcess output:\n\t" + msg);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
+        };
+
+        Process process = vm.process();
+        Debugee debugee = makeLocalDebugee(process);
+        debugee.redirectOutput(log);
+        debugee.setupVM(vm);
+
+        return debugee;
+    }
+
+    /**
+     * Launch debugee locally via the RawLaunchingConnector.
+     */
+    private Debugee localRawLaunchDebugee (VirtualMachineManager vmm,
+                                            String classToExecute,
+                                            String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        LaunchingConnector connector =
+            (LaunchingConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.launchingConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupRawLaunchingConnector(connector, classToExecute, classPath);
+
+        VirtualMachine vm;
+        try {
+            display("Launching debugee");
+            vm = connector.launch(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to launch debuggee VM:\n\t" + e);
+        } catch (VMStartException e) {
+            e.printStackTrace(log.getOutStream());
+            String msg = readVMStartExceptionOutput(e, log.getOutStream());
+            throw new Failure("Caught exception while starting debugee VM:\n\t" + e + "\nProcess output:\n\t" + msg);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching debugee VM:\n\t" + e);
+        };
+
+        Process process = vm.process();
+        Debugee debugee = makeLocalDebugee(process);
+        debugee.redirectOutput(log);
+        debugee.setupVM(vm);
+
+        return debugee;
+    }
+
+    /**
+     * Launch debugee VM locally as a local process and connect to it using
+     * <code>AttachingConnector</code>.
+     */
+    private Debugee localLaunchAndAttachDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("FindingConnector: " + argumentHandler.getConnectorName() );
+        AttachingConnector connector =
+            (AttachingConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.attachingConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
+
+        String address = makeTransportAddress();
+        String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
+        String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+
+        display("Starting java process:\n\t" + javaCmdLine);
+        Debugee debugee = startLocalDebugee(cmdLineArgs);
+        debugee.redirectOutput(log);
+
+        display("Attaching to debugee");
+        VirtualMachine vm = null;
+        IOException ioe = null;
+        for (int i = 0; i < CONNECT_TRIES; i++) {
+            try {
+                vm = connector.attach(arguments);
+                display("Debugee attached");
+                debugee.setupVM(vm);
+                return debugee;
+            } catch (IOException e) {
+                display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
+                ioe = e;
+                if (debugee.terminated()) {
+                    throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
+                }
+                try {
+                    Thread.currentThread().sleep(CONNECT_TRY_DELAY);
+                } catch (InterruptedException ie) {
+                    ie.printStackTrace(log.getOutStream());
+                    throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
+                                    + ie);
+                }
+            } catch (IllegalConnectorArgumentsException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
+            }
+        }
+        throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
+                        + " tries:\n\t" + ioe);
+    }
+
+    /**
+     * Launch debugee VM locally as a local process and connect to it using
+     * <code>ListeningConnector</code>.
+     */
+    private Debugee localLaunchAndListenDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        ListeningConnector connector =
+            (ListeningConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.listeningConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
+
+        String address = null;
+        try {
+            display("Listening for connection from debugee");
+            address = connector.startListening(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
+        };
+
+        String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
+        String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+
+        display("Starting java process:\n\t" + javaCmdLine);
+        Debugee debugee = startLocalDebugee(cmdLineArgs);
+        debugee.redirectOutput(log);
+
+        display("Waiting for connection from debugee");
+        VirtualMachine vm = null;
+        IOException ioe = null;
+        for (int i = 0; i < CONNECT_TRIES; i++) {
+            try {
+                vm = connector.accept(arguments);
+                connector.stopListening(arguments);
+                display("Debugee attached");
+                debugee.setupVM(vm);
+                return debugee;
+            } catch (IOException e) {
+                display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
+                ioe = e;
+                if (debugee.terminated()) {
+                    throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
+                }
+                try {
+                    Thread.currentThread().sleep(CONNECT_TRY_DELAY);
+                } catch (InterruptedException ie) {
+                    ie.printStackTrace(log.getOutStream());
+                    throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
+                                    + ie);
+                }
+            } catch (IllegalConnectorArgumentsException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
+            }
+        }
+        throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
+                        + " tries:\n\t" + ioe);
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Launch debugee VM remotely via <code>BindServer</code> and connect to it using
+     * <code>AttachingConnector</code>.
+     */
+    private Debugee remoteLaunchAndAttachDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        AttachingConnector connector =
+            (AttachingConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.attachingConnectors());
+
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
+
+        String address = makeTransportAddress();
+        String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
+        String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+
+        display("Starting remote java process:\n\t" + javaCmdLine);
+        Debugee debugee = startRemoteDebugee(cmdLineArgs);
+
+        display("Attaching to debugee");
+        VirtualMachine vm;
+        IOException ioe = null;
+        for (int i = 0; i < CONNECT_TRIES; i++) {
+            try {
+                vm = connector.attach(arguments);
+                display("Debugee attached");
+                debugee.setupVM(vm);
+                return debugee;
+            } catch (IOException e) {
+                display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
+                ioe = e;
+                if (debugee.terminated()) {
+                    throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
+                }
+                try {
+                    Thread.currentThread().sleep(CONNECT_TRY_DELAY);
+                } catch (InterruptedException ie) {
+                    ie.printStackTrace(log.getOutStream());
+                    throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
+                                    + ie);
+                }
+            } catch (IllegalConnectorArgumentsException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
+            }
+        }
+        throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
+                        + " tries:\n\t" + ioe);
+    }
+
+    /**
+     * Launch debugee VM remotely via <code>BindServer</code> and connect to it using
+     * <code>ListeningConnector</code>.
+     */
+    private Debugee remoteLaunchAndListenDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        ListeningConnector connector =
+            (ListeningConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.listeningConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
+
+        String address = null;
+        try {
+            display("Listening for connection from debugee");
+            address = connector.startListening(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
+        };
+
+        String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
+        String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+
+        display("Starting remote java process:\n\t" + javaCmdLine);
+        Debugee debugee = startRemoteDebugee(cmdLineArgs);
+
+        display("Waiting for connection from debugee");
+        VirtualMachine vm;
+        IOException ioe = null;
+        for (int i = 0; i < CONNECT_TRIES; i++) {
+            try {
+                vm = connector.accept(arguments);
+                connector.stopListening(arguments);
+                display("Debugee attached");
+                debugee.setupVM(vm);
+                return debugee;
+            } catch (IOException e) {
+                display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
+                ioe = e;
+                if (debugee.terminated()) {
+                    throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
+                }
+                try {
+                    Thread.currentThread().sleep(CONNECT_TRY_DELAY);
+                } catch (InterruptedException ie) {
+                    ie.printStackTrace(log.getOutStream());
+                    throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
+                                    + ie);
+                }
+            } catch (IllegalConnectorArgumentsException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
+            }
+        }
+        throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
+                        + " tries:\n\t" + ioe);
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Prompt to manually launch debugee VM and connect to it using
+     * <code>AttachingConnector</code>.
+     */
+    private Debugee manualLaunchAndAttachDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        AttachingConnector connector =
+            (AttachingConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.attachingConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
+
+        String address = makeTransportAddress();
+        String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+
+        display("Starting manual java process:\n\t" + javaCmdLine);
+        ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
+
+        VirtualMachine vm;
+        try {
+            display("Attaching to debugee");
+            vm = connector.attach(arguments);
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while attaching to debugee VM:\n\t" + e);
+        };
+        display("Debugee attached");
+
+        debugee.setupVM(vm);
+        return debugee;
+    }
+
+    /**
+     * Prompt to manually launch debugee VM and connect to it using
+     * <code>ListeningConnector</code>.
+     */
+    private Debugee manualLaunchAndListenDebugee (VirtualMachineManager vmm,
+                                                    String classToExecute,
+                                                    String classPath) {
+        display("Finding connector: " + argumentHandler.getConnectorName() );
+        ListeningConnector connector =
+            (ListeningConnector) findConnector(argumentHandler.getConnectorName(),
+                                                vmm.listeningConnectors());
+        Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
+
+        VirtualMachine vm;
+        try {
+            display("Listening for connection from debugee");
+            String address = connector.startListening(arguments);
+            String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
+            display("Starting manual java process:\n\t" + javaCmdLine);
+            ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
+            display("Waiting for connection from debugee");
+            vm = connector.accept(arguments);
+            display("Debugee attached");
+            connector.stopListening(arguments);
+            debugee.setupVM(vm);
+            return debugee;
+        } catch (IllegalConnectorArgumentsException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while listening to debugee VM:\n\t" + e);
+        }
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Make proper arguments for LaunchingConnector.
+     */
+    private Map<String,? extends Argument> setupLaunchingConnector(LaunchingConnector connector,
+                                                String classToExecute,
+                                                String classPath) {
+        display("LaunchingConnector:");
+        display("    name: " + connector.name());
+        display("    description: " + connector.description());
+        display("    transport: " + connector.transport());
+
+        Hashtable<String,? extends Argument> arguments = new Hashtable<String,Argument>(connector.defaultArguments());
+
+        Connector.Argument arg;
+
+        arg = (Connector.StringArgument) arguments.get("quote");
+        String quote = arg.value();
+
+        String cmdline = classToExecute + " " +
+                ArgumentHandler.joinArguments(argumentHandler.getRawArguments(), quote);
+
+        arg = (Connector.StringArgument) arguments.get("main");
+        arg.setValue(cmdline);
+
+        if (! argumentHandler.willDebugeeSuspended()) {
+            Connector.BooleanArgument barg = (Connector.BooleanArgument) arguments.get("suspend");
+            barg.setValue(true);
+        }
+
+/*
+        if (! argumentHandler.isJVMDIStrictMode()) {
+            arg = (Connector.StringArgument) arguments.get("options");
+            arg.setValue("strict=y");
+        }
+ */
+
+        if (! argumentHandler.isDefaultDebugeeJavaHome()) {
+            arg = (Connector.StringArgument) arguments.get("home");
+            arg.setValue(argumentHandler.getDebugeeJavaHome());
+        }
+
+        if (! argumentHandler.isDefaultLaunchExecName()) {
+            arg = (Connector.StringArgument) arguments.get("vmexec");
+            arg.setValue(argumentHandler.getLaunchExecName());
+        }
+
+        String vmArgs = "";
+
+        String vmUserArgs = argumentHandler.getLaunchOptions();
+
+        if (vmUserArgs != null) {
+            vmArgs = vmUserArgs;
+        }
+
+/*
+        if (classPath != null) {
+            vmArgs += " -classpath " + quote + classPath + quote;
+        }
+ */
+
+        if (vmArgs.length() > 0) {
+            arg = (Connector.StringArgument) arguments.get("options");
+            arg.setValue(vmArgs);
+        }
+
+        display("Connector arguments:");
+        Iterator iterator = arguments.values().iterator();
+        while (iterator.hasNext()) {
+            display("    " + iterator.next());
+        }
+        return arguments;
+    }
+
+    /**
+     * Make proper arguments for RawLaunchingConnector.
+     */
+    private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupRawLaunchingConnector(LaunchingConnector connector,
+                                                String classToExecute,
+                                                String classPath) {
+        display("RawLaunchingConnector:");
+        display("    name: " + connector.name());
+        display("    description: " + connector.description());
+        display("    transport: " + connector.transport());
+
+        Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String, com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
+
+        String connectorAddress;
+        String vmAddress;
+
+        if (argumentHandler.isSocketTransport()) {
+            connectorAddress = argumentHandler.getTransportPort();
+            vmAddress = argumentHandler.getDebugeeHost()
+                        + ":" + argumentHandler.getTransportPort();
+        } else if (argumentHandler.isShmemTransport() ) {
+            connectorAddress = argumentHandler.getTransportSharedName();
+            vmAddress=connectorAddress;
+        } else {
+            throw new TestBug("Undefined transport type for AttachingConnector");
+        }
+
+        Connector.Argument arg;
+
+        arg = (Connector.StringArgument) arguments.get("quote");
+        String quote = arg.value();
+
+        String javaCmdLine = makeCommandLineString(classToExecute, quote);
+
+        arg = (Connector.StringArgument) arguments.get("command");
+        arg.setValue(javaCmdLine);
+
+        arg = (Connector.StringArgument) arguments.get("address");
+        arg.setValue(connectorAddress);
+
+        display("Connector arguments:");
+        Iterator iterator = arguments.values().iterator();
+        while (iterator.hasNext()) {
+            display("    " + iterator.next());
+        }
+        return arguments;
+    }
+
+    /**
+     * Make proper arguments for AttachingConnector.
+     */
+    private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupAttachingConnector(AttachingConnector connector,
+                                                String classToExecute,
+                                                String classPath) {
+        display("AttachingConnector:");
+        display("    name: " + connector.name());
+        display("    description: " + connector.description());
+        display("    transport: " + connector.transport());
+
+        Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String,com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
+
+        Connector.Argument arg;
+        if (argumentHandler.isSocketTransport()) {
+            arg = (Connector.StringArgument) arguments.get("hostname");
+            arg.setValue(argumentHandler.getDebugeeHost());
+            Connector.IntegerArgument iarg = (Connector.IntegerArgument) arguments.get("port");
+            iarg.setValue(argumentHandler.getTransportPortNumber());
+        } else {
+            arg = (Connector.StringArgument) arguments.get("name");
+            arg.setValue(argumentHandler.getTransportSharedName());
+        }
+
+        display("Connector arguments:");
+        Iterator iterator = arguments.values().iterator();
+        while (iterator.hasNext()) {
+            display("    " + iterator.next());
+        }
+        return arguments;
+    }
+
+    /**
+     * Make proper arguments for ListeningConnector.
+     */
+    private Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> setupListeningConnector(ListeningConnector connector,
+                                                String classToExecute,
+                                                String classPath) {
+        display("ListeningConnector:");
+        display("    name: " + connector.name());
+        display("    description: " + connector.description());
+        display("    transport: " + connector.transport());
+
+        Hashtable<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = new Hashtable<java.lang.String,com.sun.jdi.connect.Connector.Argument>(connector.defaultArguments());
+
+        Connector.Argument arg;
+        if (argumentHandler.isSocketTransport()) {
+            if (!argumentHandler.isTransportAddressDynamic()) {
+                int port = argumentHandler.getTransportPortNumber();
+                Connector.IntegerArgument iarg = (Connector.IntegerArgument) arguments.get("port");
+                iarg.setValue(port);
+            }
+        } else {
+            String sharedName = argumentHandler.getTransportSharedName();
+            arg = (Connector.StringArgument) arguments.get("name");
+            arg.setValue(sharedName);
+        }
+
+        display("Connector arguments:");
+        Iterator iterator = arguments.values().iterator();
+        while (iterator.hasNext()) {
+            display("    " + iterator.next());
+        }
+        return arguments;
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Find connector by name from given connectors list.
+     */
+    private Connector findConnector(String connectorName, List connectors) {
+        Iterator iter = connectors.iterator();
+
+        while (iter.hasNext()) {
+            Connector connector = (Connector) iter.next();
+            if (connector.name().equals(connectorName)) {
+                return connector;
+            }
+        }
+        throw new Failure("JDI connector not found: " + connectorName);
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Launch local debuggee process with specified command line arguments
+     * and make initial <code>Debugee</code> mirror.
+     */
+    protected Debugee startLocalDebugee(String[] cmdArgs) {
+        Process process = null;
+
+        try {
+            process = launchProcess(cmdArgs);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching local debuggee VM process:\n\t"
+                            + e);
+        }
+
+        return makeLocalDebugee(process);
+    }
+
+    /**
+     * Launch remote debuggee process with specified command line arguments
+     * and make initial <code>Debugee</code> mirror.
+     */
+    protected RemoteLaunchedDebugee startRemoteDebugee(String[] cmdArgs) {
+        try {
+            launchRemoteProcess(cmdArgs);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while launching remote debuggee VM process:\n\t"
+                            + e);
+        }
+
+        RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
+
+        Finalizer finalizer = new Finalizer(debugee);
+        finalizer.activate();
+
+        return debugee;
+    }
+
+    /**
+     * Launch manual debuggee process with specified command line arguments
+     * and make initial <code>Debugee</code> mirror.
+     */
+    protected ManualLaunchedDebugee startManualDebugee(String cmd) {
+        ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
+        debugee.launchDebugee(cmd);
+
+        Finalizer finalizer = new Finalizer(debugee);
+        finalizer.activate();
+
+        return debugee;
+    }
+
+    public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) {
+        StringBuffer msg = new StringBuffer();
+        try (InputStream is = e.process().getInputStream()) {
+            msg.append("\tstdout: ").append(new String(readAllBytes(is))).append('\n');
+        } catch (IOException e1) {
+            log.println("Could not read normal output from launched process:" + e1);
+        }
+        try (InputStream is = e.process().getErrorStream()) {
+            msg.append("\tstderr: ").append(new String(readAllBytes(is)));
+        } catch (IOException e1) {
+            log.println("Could not read error output from launched process:" + e1);
+        }
+        return msg.toString();
+    }
+
+    /**
+     * Copied from the JDK 9 implementation in InputStream.java
+     */
+    private static byte[] readAllBytes(InputStream is) throws IOException {
+        final int DEFAULT_BUFFER_SIZE = 8192;
+        final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
+
+        byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
+        int capacity = buf.length;
+        int nread = 0;
+        int n;
+        for (;;) {
+            // read to EOF which may read more or less than initial buffer size
+            while ((n = is.read(buf, nread, capacity - nread)) > 0)
+                nread += n;
+
+            // if the last call to read returned -1, then we're done
+            if (n < 0)
+                break;
+
+            // need to allocate a larger buffer
+            if (capacity <= MAX_BUFFER_SIZE - capacity) {
+                capacity = capacity << 1;
+            } else {
+                if (capacity == MAX_BUFFER_SIZE)
+                    throw new OutOfMemoryError("Required array size too large");
+                capacity = MAX_BUFFER_SIZE;
+            }
+            buf = Arrays.copyOf(buf, capacity);
+        }
+        return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
+    }
+
+}
+
+
+/**
+ * Mirror of locally launched debugee.
+ */
+final class LocalLaunchedDebugee extends Debugee {
+
+    /** Enwrap the locally started VM process. */
+    public LocalLaunchedDebugee (Process process, Binder binder) {
+        super(binder);
+        this.process = process;
+        checkTermination = true;
+    }
+
+    // ---------------------------------------------- //
+
+    /** Return exit status of the debugee VM. */
+    public int getStatus () {
+        return process.exitValue();
+    }
+
+    /** Check whether the debugee VM has been terminated. */
+    public boolean terminated () {
+        if (process == null)
+            return true;
+
+        try {
+            int value = process.exitValue();
+            return true;
+        } catch (IllegalThreadStateException e) {
+            return false;
+        }
+    }
+
+    // ---------------------------------------------- //
+
+    /** Kill the debugee VM. */
+    protected void killDebugee () {
+        super.killDebugee();
+        if (!terminated()) {
+            log.display("Killing debugee VM process");
+            process.destroy();
+        }
+    }
+
+    /** Wait until the debugee VM shutdown or crash. */
+    protected int waitForDebugee () throws InterruptedException {
+        int code = process.waitFor();
+        return code;
+    }
+
+    /** Get a pipe to write to the debugee's stdin stream. */
+    protected OutputStream getInPipe () {
+        return process.getOutputStream();
+    }
+
+    /** Get a pipe to read the debugee's stdout stream. */
+    protected InputStream getOutPipe () {
+        return process.getInputStream();
+    }
+
+    /** Get a pipe to read the debugee's stderr stream. */
+    protected InputStream getErrPipe () {
+        return process.getErrorStream();
+    }
+}
+
+
+/**
+ * Mirror of remotely launched debugee.
+ */
+final class RemoteLaunchedDebugee extends Debugee {
+
+    /** Enwrap the remotely started VM process. */
+    public RemoteLaunchedDebugee (Binder binder) {
+        super(binder);
+    }
+
+    // ---------------------------------------------- //
+
+    /** Return exit status of the debugee VM. */
+    public int getStatus () {
+        return binder.getRemoteProcessStatus();
+    }
+
+    /** Check whether the debugee VM has been terminated. */
+    public boolean terminated () {
+        return binder.isRemoteProcessTerminated();
+    }
+
+    // ---------------------------------------------- //
+
+    /** Kill the debugee VM. */
+    protected void killDebugee () {
+        super.killDebugee();
+        if (!terminated()) {
+            binder.killRemoteProcess();
+        }
+    }
+
+    /** Wait until the debugee VM shutdown or crash. */
+    protected int waitForDebugee () {
+        return binder.waitForRemoteProcess();
+    }
+
+    /** Get a pipe to write to the debugee's stdin stream. */
+    protected OutputStream getInPipe () {
+        return null;
+    }
+
+    /** Get a pipe to read the debugee's stdout stream. */
+    protected InputStream getOutPipe () {
+        return null;
+    }
+
+    /** Get a pipe to read the debugee's stderr stream. */
+    protected InputStream getErrPipe () {
+        return null;
+    }
+
+    public void redirectStdout(OutputStream out) {
+    }
+
+    public void redirectStdout(Log log, String prefix) {
+    }
+
+    public void redirectStderr(OutputStream out) {
+    }
+
+    public void redirectStderr(Log log, String prefix) {
+    }
+}
+
+
+/**
+ * Mirror of manually launched debugee.
+ */
+final class ManualLaunchedDebugee extends Debugee {
+    /** Enwrap the manually started VM process. */
+    public ManualLaunchedDebugee (Binder binder) {
+        super(binder);
+        makeInputReader();
+    }
+
+    // ---------------------------------------------- //
+
+    private int exitCode = 0;
+    private boolean finished = false;
+    private static BufferedReader bin = null;
+
+    public void launchDebugee(String commandLine) {
+        makeInputReader();
+
+        putMessage("Launch target VM using such command line:\n"
+                    + commandLine);
+        String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
+        for ( ; ; ) {
+            if (answer.equals("yes"))
+                break;
+            if (answer.equals("no"))
+                throw new Failure ("Unable to manually launch debugee VM");
+            answer = askQuestion("Wrong answer. Please type yes or no", "yes");
+        }
+    }
+
+    private static void makeInputReader() {
+        if (bin == null) {
+            bin = new BufferedReader(new InputStreamReader(System.in));
+        }
+    }
+
+    private static void destroyInputReader() {
+        if (bin != null) {
+            try {
+                bin.close();
+            } catch (IOException e) {
+//                e.printStackTrace(log.getOutStream());
+                throw new Failure("Caught exception while closing input stream:\n\t" + e);
+            }
+            bin = null;
+        }
+    }
+
+    private static void putMessage(String msg) {
+        System.out.println("\n>>> " + msg);
+    }
+
+    private static String askQuestion(String question, String defaultAnswer) {
+        try {
+            System.out.print("\n>>> " + question);
+            System.out.print(" [" + defaultAnswer + "] ");
+            System.out.flush();
+            String answer = bin.readLine();
+            if (answer.equals(""))
+                return defaultAnswer;
+            return answer;
+        } catch (IOException e) {
+//            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while reading answer:\n\t" + e);
+        }
+    }
+
+    /** Return exit status of the debugee VM. */
+    public int getStatus () {
+        if (! finished) {
+            throw new Failure("Unable to get status of debugee VM: process still alive");
+        }
+        return exitCode;
+    }
+
+    /** Check whether the debugee VM has been terminated. */
+    public boolean terminated () {
+        return finished;
+    }
+
+    // ---------------------------------------------- //
+
+    /** Kill the debugee VM. */
+    protected void killDebugee () {
+        super.killDebugee();
+        if (!terminated()) {
+            putMessage("Kill launched VM");
+            String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
+            for ( ; ; ) {
+                if (answer.equals("yes")) {
+                    finished = true;
+                    break;
+                }
+                if (answer.equals("no"))
+                    throw new Failure ("Unable to manually kill debugee VM");
+                answer = askQuestion("Wrong answer. Please type yes or no", "yes");
+            }
+        }
+    }
+
+    /** Wait until the debugee VM shutdown or crash. */
+    protected int waitForDebugee () {
+        putMessage("Wait for launched VM to exit.");
+        String answer = askQuestion("What is VM exit code?", "95");
+        for ( ; ; ) {
+            try {
+                exitCode = Integer.parseInt(answer);
+                break;
+            } catch (NumberFormatException e) {
+                answer = askQuestion("Wrong answer. Please type integer value", "95");
+            }
+        }
+        finished = true;
+        return exitCode;
+    }
+
+    /** Get a pipe to write to the debugee's stdin stream. */
+    protected OutputStream getInPipe () {
+        return null;
+    }
+
+    /** Get a pipe to read the debugee's stdout stream. */
+    protected InputStream getOutPipe () {
+        return null;
+    }
+
+    /** Get a pipe to read the debugee's stderr stream. */
+    protected InputStream getErrPipe () {
+        return null;
+    }
+
+    public void redirectStdout(OutputStream out) {
+    }
+
+    public void redirectStdout(Log log, String prefix) {
+    }
+
+    public void redirectStderr(OutputStream out) {
+    }
+
+    public void redirectStderr(Log log, String prefix) {
+    }
+
+    public void close() {
+        destroyInputReader();
+        super.close();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ConnectorTest.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import com.sun.jdi.connect.*;
+import com.sun.jdi.*;
+import java.io.*;
+import java.util.*;
+
+import nsk.share.*;
+import nsk.share.jpda.*;
+
+/*
+ * This class contains several common methods used by connector tests.
+ */
+public abstract class ConnectorTest {
+    protected Log log;
+
+    protected VirtualMachine vm;
+
+    protected int attempts; // attempts to connect to the debuggee VM
+
+    protected int delay; // delay between connection attempts
+
+    protected IORedirector outRedirector;
+
+    protected IORedirector errRedirector;
+
+    protected ArgHandler argHandler;
+
+    protected boolean isTestFailed;
+
+    // set test status 'FAILED'
+    protected void testFailed() {
+        isTestFailed = true;
+    }
+
+    // check if tested functionality implemented on current platform
+    protected boolean shouldPass() {
+        return argHandler.shouldPass(getConnectorName());
+    }
+
+    abstract protected void doTest();
+
+    abstract protected String getConnectorName();
+
+    abstract protected String getDebuggeeClass();
+
+    static public class ArgHandler extends ArgumentHandler {
+        public ArgHandler(String[] args) {
+            super(args);
+
+        }
+
+        protected boolean checkOption(String option, String value) {
+            if (super.checkOption(option, value))
+                return true;
+
+            if (option.equals("testWorkDir"))
+                return true;
+
+            if (option.equals("waitVMStartEvent"))
+                return true;
+
+            return false;
+        }
+
+        public String getTestWorkDir() {
+            String dir = options.getProperty("testWorkDir");
+
+            if (dir.endsWith(File.separator)) {
+                dir = dir.substring(0, dir.length() - 1);
+            }
+
+            return dir;
+        }
+
+        public boolean waitVMStartEvent() {
+            return options.containsKey("waitVMStartEvent");
+        }
+    }
+
+    /*
+     * Subclasses can provide another ArgumentHandlers
+     */
+    protected ArgHandler createArgumentHandler(String[] args) {
+        return new ArgHandler(args);
+    }
+
+    protected void init(String[] args, PrintStream out) {
+        argHandler = createArgumentHandler(args);
+
+        log = new Log(out, argHandler);
+
+        delay = argHandler.getConnectionDelay();
+
+        // calculate number of connection attempts to not exceed WAITTIME
+        long timeout = argHandler.getWaitTime() * 60 * 1000;
+        attempts = (int) (timeout / delay);
+    }
+
+    protected int runIt(String argv[], PrintStream out) {
+        try {
+            init(argv, out);
+
+            if (shouldPass()) {
+                log.display("Tested functionality isn't implemented on this platform. Treat test as passed.");
+                return Consts.TEST_PASSED;
+            }
+
+            doTest();
+
+            if (isTestFailed)
+                return Consts.TEST_FAILED;
+            else
+                return Consts.TEST_PASSED;
+
+        } catch (Throwable t) {
+            out.println("Unexpected exception: " + t);
+            t.printStackTrace(out);
+            return Consts.TEST_FAILED;
+        }
+    }
+
+    protected void waitForVMInit(VirtualMachine vm) {
+        Debugee.waitForVMInit(vm, log, argHandler.getWaitTime() * 60 * 1000);
+    }
+
+    // set connector argument value with given name
+    protected void setConnectorArg(Map<String, Connector.Argument> args, String argName, String value) {
+        for (String key : args.keySet()) {
+            Connector.Argument arg = args.get(key);
+            if (arg.name().equals(argName)) {
+                arg.setValue(value);
+                return;
+            }
+        }
+
+        throw new Error("There is no argument '" + argName + "'");
+    }
+
+    // try attach to target VM using attaching connector
+    protected VirtualMachine tryAttach(AttachingConnector connector, Map<String, Connector.Argument> cArgs) {
+        // make several attempts to connect to the debuggee VM until WAITTIME exceeds
+        for (int i = 0; i < attempts; i++) {
+            try {
+                return connector.attach(cArgs);
+            } catch (IOException e) {
+                // could not connect; sleep a few and make new attempt
+                log.display("Connection attempt #" + i + " failed: " + e);
+                e.printStackTrace(log.getOutStream());
+                try {
+                    Thread.sleep(delay);
+                } catch (InterruptedException ie) {
+                    testFailed();
+                    log.complain("TEST INCOMPLETE: interrupted sleep: " + ie);
+                    ie.printStackTrace(log.getOutStream());
+                }
+            } catch (IllegalConnectorArgumentsException e) {
+                testFailed();
+                log.complain("TEST: Illegal connector arguments: " + e.getMessage());
+                return null;
+            } catch (Exception e) {
+                testFailed();
+                log.complain("TEST: Internal error: " + e.getMessage());
+                e.printStackTrace(log.getOutStream());
+                return null;
+            }
+        }
+
+        testFailed();
+        // return null after all attempts failed
+        log.complain("FAILURE: all attempts to connect to the debuggee VM failed");
+        return null;
+    }
+
+    // try find connector with given name
+    protected Connector findConnector(String connectorName) {
+        List<Connector> connectors = Bootstrap.virtualMachineManager().allConnectors();
+        Iterator<Connector> iter = connectors.iterator();
+
+        while (iter.hasNext()) {
+            Connector connector = (Connector) iter.next();
+            if (connector.name().equals(connectorName)) {
+                log.display("Connector name=" + connector.name() + "\n\tdescription=" + connector.description() + "\n\ttransport="
+                        + connector.transport().name());
+                return connector;
+            }
+        }
+        throw new Error("No appropriate connector");
+    }
+
+    // wait when debuggee process finishes and check exit code
+    protected void waitDebuggeeExit(Debugee debuggee) {
+        log.display("\nwaiting for debuggee VM exit");
+        int code = debuggee.waitFor();
+        if (code != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) {
+            testFailed();
+            log.complain("Debuggee VM has crashed: exit code=" + code);
+            return;
+        }
+        log.display("debuggee VM: exit code=" + code);
+    }
+
+    // wait 'READY' command from debuggee VM (this method is used by debuggers establishing socket connection with debuggee VM)
+    protected boolean waitReadyCommand(IOPipe pipe) {
+        String command = pipe.readln();
+        log.display("Command: " + command);
+
+        if (!command.equals(AbstractDebuggeeTest.COMMAND_READY)) {
+            testFailed();
+            log.complain("Unexpected debuggee answer: " + command + ", expected is " + AbstractDebuggeeTest.COMMAND_READY);
+            return false;
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/Debugee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import nsk.share.*;
+import nsk.share.jpda.*;
+
+import com.sun.jdi.*;
+import com.sun.jdi.request.*;
+import com.sun.jdi.event.*;
+
+import java.util.*;
+
+/**
+ * This class is used to interact with debugee VM using JDI features.
+ * <p>
+ * This class is wrapper for debugee VM constructed by <code>Binder</code>
+ * and it uses <code>com.sun.jdi.VirtualMachine</code> to interact with debugee VM.
+ * <p>
+ * In addition to the general abities to control of debugee VM process,
+ * provided by the base class <code>DebugeeProcess</code>, this class
+ * adds also several service methods over the JDI features to simplify interaction
+ * with debugee VM (such as finding classes, setting breakpoints,
+ * handling events, and so on.).
+ *
+ * @see Binder
+ * @see DebugeeProcess
+ */
+abstract public class Debugee extends DebugeeProcess {
+    /**
+     * Mirror of the debugee VM. This must be initialized by every
+     * particular non-abstract class extending Debugee class.
+     */
+    protected VirtualMachine vm = null;
+
+    /** Binder that created this debugee. */
+    protected Binder binder = null;
+
+    /** Argument handler. */
+    protected ArgumentHandler argumentHandler = null;
+
+    /** Create new <code>Debugee</code> object for a given binder. */
+    protected Debugee (Binder binder) {
+        super(binder);
+        this.binder = binder;
+        this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
+    }
+
+    /** Setup <code>Debugee</code> object with given VM mirror. */
+    public void setupVM(VirtualMachine vm) {
+        if (this.vm != null) {
+            throw new TestBug("Setting duplicated VM mirror for Debugee object");
+        }
+        this.vm = vm;
+        int traceMode = argumentHandler.getTraceMode();
+        if (traceMode != VirtualMachine.TRACE_NONE) {
+            display("Setting JDI trace mode to: " + argumentHandler.getTraceModeString());
+            setDebugTraceMode(traceMode);
+        }
+    }
+
+    /** Return <code>Binder</code> of the debugee object. */
+    public Binder getBinder() {
+        return binder;
+    }
+
+    /** Return JDI mirror of the debugee VM. */
+    public VirtualMachine VM() {
+        return vm;
+    }
+
+    /** Return <code>EventRequestManager</code> of the debugee object. */
+    public EventRequestManager getEventRequestManager() {
+        return vm.eventRequestManager();
+    }
+
+    // --------------------------------------------------- //
+
+    /** List of the currently running threads. */
+    public ThreadReference[] threads () {
+        List list = vm.allThreads();
+        int size = list.size();
+        ThreadReference array[] = new ThreadReference[size];
+        Iterator iterator = list.iterator();
+        for (int i = 0; i < size; i++)
+            array[i] = (ThreadReference) iterator.next();
+        if (iterator.hasNext())
+            throw new Oddity("extra element in a list?");
+        return array;
+    }
+
+    /** List of all types loaded by the debugee VM. */
+    public ReferenceType[] classes() {
+        return classes(null);
+    }
+
+    /**
+     * List of all classes of the given <code>name</code> loaded by
+     * the debugee VM; or list of all classes, if <code>name</code>
+     * is <code>null</code>.
+     */
+    private ReferenceType[] classes (String name) {
+        List list = (name==null)? vm.allClasses(): vm.classesByName(name);
+        int size = list.size();
+        ReferenceType array[] = new ReferenceType [ size ];
+        Iterator iterator = list.iterator();
+        for (int i=0; i<size; i++)
+            array[i] = (ReferenceType) iterator.next();
+        if (iterator.hasNext())
+            throw new Oddity("extra element in a list?");
+        return array;
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Return mirror for the only class of the given <code>name</code>
+     * loaded by the debugee VM; or throw TestBug exception if there
+     * are more than one such class found. TestFailure exception
+     * will be thrown in case when mirrors for classes with different
+     * names or duplicated mirrors were returned.
+     * Return <code>null</code> if there is no such class loaded.
+     */
+    public ReferenceType classByName (String name) {
+        ReferenceType classes[] = this.classes(name);
+
+        // if on first call debuggee doesn't return needed class try get this class one more time after delay to avoid 6446633
+        if (classes == null || classes.length == 0) {
+            try {
+                Thread.sleep(1000);
+            }
+            catch(InterruptedException e) {
+                throw new TestBug("Unexpected InterruptedException");
+            }
+
+            classes = this.classes(name);
+        }
+
+        if (classes == null || classes.length == 0)
+            return null;
+
+        // analyze returned mirrors and throw appropriate exception
+        if (classes.length > 1) {
+            boolean duplicatesFound = false;
+            boolean differentNamesFound = false;
+            boolean visited[] = new boolean[classes.length];
+            complain("Classes that were found for name \"" + name + "\":");
+            for(ReferenceType klass : classes) {
+                complain("\t" + klass);
+            }
+            for(int c = 0; c < classes.length; c++) {
+                if(visited[c]) {
+                    continue;
+                }
+                if(!classes[c].name().equals(name)) {
+                    differentNamesFound = true;
+                    continue;
+                }
+                for(int i = c + 1; i < classes.length; i++) {
+                    if(visited[i]) {
+                        continue;
+                    } else {
+                        visited[i] = true;
+                    }
+                    if(classes[c].classLoader() == classes[i].classLoader()) {
+                        duplicatesFound = true;
+                    }
+                }
+            }
+            if(duplicatesFound) {
+                throw new TestFailure("classes with the same name and " +
+                                      "loaded with the same class loader " +
+                                      "were found.");
+            } else if(differentNamesFound) {
+                throw new TestFailure("class with name different from '" + name +
+                                      "' was returned by VirutualMachine.classesByName.");
+            } else {
+                throw new TestBug("found " + classes.length + " such classes: " + name);
+            }
+        }
+        return classes[0];
+    }
+
+    /**
+     * Return mirror for the only method of the given <code>refType</code>
+     * class in the debugee VM; or throw TestBug exception if there
+     * are more than one such method found. Return <code>null</code> if
+     * there is no such method found.
+     */
+    public Method methodByName(ReferenceType refType, String name) {
+        List methods = refType.methodsByName(name);
+        if (methods == null || methods.isEmpty()) return null;
+        if (methods.size() > 1)
+            throw new TestBug(
+                "found " + methods.size() + " such methods: " + name);
+        Method method = (Method)methods.get(0);
+        return method;
+    }
+
+    /**
+     * Return a currently running thread of the given <code>name</code>; or
+     * throw TestBug exception if there are more than one such thread found.
+     * Return <code>null</code> if there is no such thread.
+     */
+    public ThreadReference threadByName (String name) {
+        ThreadReference threads[] = this.threads();
+        int count = 0, index = -1;
+        for (int i = 0; i < threads.length; i++) {
+            if (threads[i].name().compareTo(name)==0) {
+                count++;
+                index = i;
+            }
+        }
+        if (count == 0)
+            return null;
+        if (count > 1)
+            throw new TestBug(
+                "found " + count + " such threads: " + name);
+        return threads[index];
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Returns Location object for given line number in specified method or null
+     * if no location for this line is found.
+     *
+     * @param method method mirror containing given line number
+     * @param line line number to find location
+     */
+    public Location getLineLocation(Method method, int line) {
+        List locs = null;
+        try {
+            locs = method.allLineLocations();
+        } catch(AbsentInformationException e) {
+            throw new TestBug("Unable to find location for line " + line + ": " + e);
+        }
+        Iterator iter = locs.iterator();
+        while (iter.hasNext()) {
+            Location location = (Location)iter.next();
+            if (location.lineNumber() == line) {
+                return location;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns Location object for given line number in specified reference type or null
+     * if no location for this line is found.
+     *
+     * @param refType reference type mirror containing given line number
+     * @param line line number to find location
+     */
+    public Location getLineLocation(ReferenceType refType, int line) {
+        List locs = null;
+        try {
+            locs = refType.allLineLocations();
+        } catch(AbsentInformationException e) {
+            throw new TestBug("Unable to find location for line " + line + ": " + e);
+        }
+        Iterator iter = locs.iterator();
+        while (iter.hasNext()) {
+            Location location = (Location)iter.next();
+            if (location.lineNumber() == line) {
+                return location;
+            }
+        }
+        return null;
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Make disabled breakpoint to given location and return BreakpointRequest.
+     *
+     * @param location location to set breakpoint
+     *
+     * @see #setBreakpoint(Method, int)
+     * @see #setBreakpoint(ReferenceType, String, int)
+     */
+    public BreakpointRequest makeBreakpoint(Location location) {
+        EventRequestManager evm = getEventRequestManager();
+        BreakpointRequest request = evm.createBreakpointRequest(location);
+        display("Breakpoint set:\n\t" + request);
+        return request;
+    }
+
+    /**
+     * Make disabled breakpoint to given line number in specified method
+     * and return BreakpointRequest.
+     *
+     * @param method method mirror to set breakpoint
+     * @param lineNumber line number inside the method
+     *
+     * @throws Failure if no location found for specified line number
+     *
+     * @see #makeBreakpoint(Location)
+     * @see #makeBreakpoint(ReferenceType, String, int)
+     */
+    public BreakpointRequest makeBreakpoint(Method method, int lineNumber) {
+        Location location = getLineLocation(method, lineNumber);
+        if (location == null) {
+            throw new Failure("No location found for setting breakpoint to line " + lineNumber);
+        }
+        return makeBreakpoint(location);
+    }
+
+    /**
+     * Make disabled breakpoint to given line number for specified method name
+     * of the given reference type and return BreakpointRequest.
+     *
+     * @param refType reference type for specified method
+     * @param methodName method name to set breakpoint
+     * @param lineNumber line number inside the method
+     *
+     * @throws Failure if no location found for specified line number
+     *
+     * @see #makeBreakpoint(Method, int)
+     */
+    public BreakpointRequest makeBreakpoint(ReferenceType refType,
+                                            String methodName, int lineNumber) {
+        Method method = methodByName(refType, methodName);
+        if (method == null) {
+            throw new Failure("No method found for setting breakpoint: " + methodName);
+        }
+        return makeBreakpoint(method, lineNumber);
+    }
+
+    /**
+     * Set and enable breakpoint to given line number for specified method
+     * and return BreakpointRequest.
+     *
+     * @param method method mirror to set breakpoint
+     * @param lineNumber line number inside the method
+     *
+     * @throws Failure if no location found for specified line number
+     *
+     * @see #setBreakpoint(ReferenceType, String, int)
+     */
+    public BreakpointRequest setBreakpoint(Method method, int lineNumber) {
+        BreakpointRequest request = makeBreakpoint(method, lineNumber);
+        request.enable();
+        return request;
+    }
+
+    /**
+     * Set and enable breakpoint to given line number for specified method name
+     * of the given reference type and return BreakpointRequest.
+     *
+     * @param refType reference type for specified method
+     * @param methodName method name to set breakpoint
+     * @param lineNumber line number inside the method
+     *
+     * @throws Failure if no location found for specified line number
+     *
+     * @see #setBreakpoint(Method, int)
+     */
+    public BreakpointRequest setBreakpoint(ReferenceType refType,
+                                            String methodName, int lineNumber) {
+        BreakpointRequest request = makeBreakpoint(refType, methodName, lineNumber);
+        request.enable();
+        return request;
+    }
+
+    // --------------------------------------------------- //
+
+    /** Suspend the debugee VM. */
+    public void suspend() {
+        vm.suspend();
+    }
+
+    /** Resume the debugee VM. */
+    public void resume() {
+        vm.resume();
+    }
+
+    /** Dispose the debugee VM. */
+    public void dispose() {
+        vm.dispose();
+    }
+
+    /*
+     * Set internal JDI tracing mode.
+     */
+    public void setDebugTraceMode(int traceMode) {
+        vm.setDebugTraceMode(traceMode);
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Wait for the requested event and skip other events.
+     *
+     * @param request non-null value for events generated by this
+     * event request; null value for <code>VMStartEvent</code>.
+     * @param timeout timeout in milliseconds to wait for the requested event.
+     *
+     * @throws InterruptedException if another thread has interrupted this thread
+     */
+    public Event waitingEvent(EventRequest request, long timeout)
+                                                throws InterruptedException {
+
+        if (request == null) {
+            throw new Failure("Null request specified for waiting events: " + request);
+        }
+
+        long timeToFinish = System.currentTimeMillis() + timeout;
+        long timeLeft = timeout;
+        boolean exit = false;
+
+        display("Waiting for event by request:\n\t" + request);
+
+        EventQueue eventQueue = vm.eventQueue();
+        while (timeLeft > 0 && !exit) {
+
+            EventSet eventSet = eventQueue.remove(timeLeft);
+            if (eventSet == null) {
+                continue;
+            }
+
+            EventIterator eventIterator = eventSet.eventIterator();
+            while (eventIterator.hasNext()) {
+
+                Event event = eventIterator.nextEvent();
+                EventRequest eventRequest = event.request();
+
+                if (request == eventRequest || request.equals(eventRequest)) {
+                    display("Got requested event:\n\t" + event);
+                    return event;
+                } else if (event instanceof VMDeathEvent) {
+                    display("Ignore unexpected VMDeathEvent");
+                } else if (event instanceof VMDisconnectEvent) {
+                    display("Got unexpected VMDisconnectEvent");
+                    exit = true;
+                    break;
+                } else {
+                    display("Ignore unexpected event:\n\t" + event);
+                } // if
+
+            } // while
+
+            timeLeft = timeToFinish - System.currentTimeMillis();
+
+        } // while
+
+        return null;
+    }
+
+    /*
+     * Wait for VM to initialize by receiving initial VM_START event for specified timeout.
+     */
+    public void waitForVMInit(long timeout) {
+        waitForVMInit(vm ,log, timeout);
+    }
+
+    /*
+     * This static method is also used by nsk.share.jdi.ConnectorTest
+     */
+    static public void waitForVMInit(VirtualMachine vm, Log log, long timeout) {
+        try {
+            EventSet eventSet = vm.eventQueue().remove(timeout);
+            if (eventSet == null) {
+                throw new Failure("No VMStartEvent received for timeout: " + timeout + " ms");
+            }
+            EventIterator iterator = eventSet.eventIterator();
+            while (iterator.hasNext()) {
+                Event event = iterator.nextEvent();
+                if (event == null) {
+                    throw new Failure("Null event received instead of VMStartEvent");
+                }
+                if (event instanceof VMStartEvent) {
+                    log.display("Initial VMStartEvent received: " + event);
+                } else {
+                    throw new Failure("Unexpected event received instead of VMStartEvent: " + event);
+                }
+            }
+            int suspendPolicy = eventSet.suspendPolicy();
+            if (suspendPolicy != EventRequest.SUSPEND_ALL) {
+                throw new Failure("Suspend policy of VMStartEvent is not SUSPEND_ALL: " + suspendPolicy);
+            }
+        } catch (InterruptedException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Thread interrupted while waiting for VMStartEvent:\n\t" + e);
+        }
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Bind to debuggee VM using <code>Binder</code> and make initial
+     * synchronization via IOPipe.
+     *
+     * @param argHandler command line arguments handler to make <code>Binder</code> object
+     * @param log <code>Log</code> object to log messages
+     * @param mainClassName main class of debugee
+     *
+     * @throws Failure if there were problems with binding to debuggee VM
+     *
+     * @see Binder#bindToDebugee(String)
+     */
+    public static Debugee prepareDebugee(ArgumentHandler argHandler, Log log,
+                                                String mainClassName) {
+        Binder binder = new Binder(argHandler, log);
+        Debugee debugee = binder.bindToDebugee(mainClassName);
+
+        debugee.createIOPipe();
+
+        debugee.redirectStderr(log, DEBUGEE_STDERR_LOG_PREFIX);
+        debugee.resume();
+
+        debugee.receiveExpectedSignal("ready");
+
+        return debugee;
+    }
+
+    /**
+     * Send <code>"quit"</code> signal, wait for debugee VM exit and check exit.
+     *
+     * @throws Failure if exit status is not <code>Consts.JCK_STATUS_BASE</code>
+     *
+     * @see #endDebugee()
+     */
+    public void quit() {
+        sendSignal("quit");
+        int status = endDebugee();
+        if ( status != Consts.JCK_STATUS_BASE ) {
+            throw new Failure("Got unexpected debugee VM exit status: " + status
+                                + " (not " + Consts.JCK_STATUS_BASE + ")");
+        }
+        display("Got expected debugee VM exit status: " + status);
+    }
+
+    /*
+     * Dispose debuggee VM, wait for it to exit, close all resources and return
+     * exit status code.
+     */
+    public int endDebugee() {
+        if (vm != null) {
+            try {
+                vm.dispose();
+            } catch (VMDisconnectedException ignore) {
+            }
+            vm = null;
+        }
+        return waitFor();
+    }
+
+    /*
+     * Print information about all threads in debuggee VM
+     */
+    protected void printThreadsInfo(VirtualMachine vm)  {
+        try {
+            log.display("------------ Try to print debuggee threads before killing process ------------");
+            if (vm == null) {
+                log.display("Can't print threads info because 'vm' is null");
+                return;
+            }
+            List<ThreadReference> threads = vm.allThreads();
+            log.display("Threads: " + threads);
+            log.display("Total threads: " + threads.size());
+            for (ThreadReference thread : threads) {
+                log.display("\nThread: " + thread.name());
+                log.display("Is suspended: " + thread.isSuspended());
+                log.display("Is at breakpoint: " + thread.isAtBreakpoint());
+                boolean wasSuspended = false;
+                try {
+                    if (!thread.isSuspended()) {
+                        log.display("\n suspend thread to get its stack \n");
+                        thread.suspend();
+                        wasSuspended = true;
+                    }
+                    log.display("Stack frame count: " + thread.frameCount());
+                    if (thread.frameCount() > 0) {
+                        log.display("Frames:");
+                        for (StackFrame frame : thread.frames()) {
+                            Location location = frame.location();
+                            log.display(location.declaringType().name() + "." + location.method().name() + ", line: " + location.lineNumber());
+                        }
+                    }
+                } finally {
+                    if (wasSuspended) {
+                        log.display("\n resume thread \n");
+                        thread.resume();
+                    }
+                }
+            }
+            log.display("----------------------------------------------------------------------");
+        } catch (Throwable t) {
+            log.complain("");
+            t.printStackTrace(log.getOutStream());
+        }
+    }
+
+    /**
+     * Force debugge VM to exit using JDI interface if possible.
+     */
+    protected void killDebugee() {
+        try {
+            // print information about debuggee threads to simplify failure analysis
+            printThreadsInfo(vm);
+        } finally {
+            if (vm != null) {
+                try {
+                    display("Killing debuggee by forcing target VM to exit");
+                    vm.exit(97);
+                    display("Debugee VM successfully forced to exit");
+                    vm = null;
+                } catch (VMDisconnectedException e) {
+                    display("Ignore VMDisconnectedException while forcing debuggee VM to exit:\n\t"
+                            + e);
+                }
+            }
+        }
+    }
+
+    public boolean isJFR_active() {
+        String opts = argumentHandler.getLaunchOptions();
+        int unlockPos = opts.indexOf("-XX:+UnlockCommercialFeatures");
+        int jfrPos = opts.indexOf("-XX:+FlightRecorder");
+
+        if (unlockPos >= 0 && jfrPos >= 0 && jfrPos > unlockPos)
+            return true;
+        else
+            return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/DebuggeeEventData.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+/*
+ * Classes included in this class represent JDI events on debuggee VM's side
+ * All this classes contain information about JDI event which should be generated during test execution
+ */
+public class DebuggeeEventData {
+    // base event data class
+    public static class DebugEventData {
+    }
+
+    /*
+     * debug information about monitor event
+     */
+    public static class DebugMonitorEventData extends DebugEventData {
+        public DebugMonitorEventData(Object monitor, Thread thread, Object eventObject) {
+            this.monitor = monitor;
+            this.thread = thread;
+            this.eventObject = eventObject;
+        }
+
+        public Object monitor;
+
+        public Thread thread;
+
+        public Object eventObject;
+    }
+
+    /*
+     * information about MonitorContendedEnterEvent
+     */
+    public static class DebugMonitorEnterEventData extends DebugMonitorEventData {
+        public DebugMonitorEnterEventData(Object monitor, Thread thread, Object eventObject) {
+            super(monitor, thread, eventObject);
+        }
+    }
+
+    /*
+     * information about MonitorContendedEnteredEvent
+     */
+    public static class DebugMonitorEnteredEventData extends DebugMonitorEventData {
+        public DebugMonitorEnteredEventData(Object monitor, Thread thread, Object eventObject) {
+            super(monitor, thread, eventObject);
+        }
+    }
+
+    /*
+     * information about MonitorWaitEvent
+     */
+    public static class DebugMonitorWaitEventData extends DebugMonitorEventData {
+        public long timeout;
+
+        public DebugMonitorWaitEventData(Object monitor, Thread thread, long timeout, Object eventObject) {
+            super(monitor, thread, eventObject);
+            this.timeout = timeout;
+        }
+    }
+
+    /*
+     * information about MonitorWaitedEvent
+     */
+    public static class DebugMonitorWaitedEventData extends DebugMonitorEventData {
+        public boolean timedout;
+
+        public DebugMonitorWaitedEventData(Object monitor, Thread thread, boolean timedout, Object eventObject) {
+            super(monitor, thread, eventObject);
+            this.timedout = timedout;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/DebuggerEventData.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+
+/*
+ * Classes included in this class represent JDI events on debugger VM's side
+ * All this classes contain information about JDI event which should be generated during test execution,
+ * instances of this classes should be created using instances of corresponding classes from debuggee VM
+ */
+public class DebuggerEventData
+{
+    static abstract class DebugEventData
+    {
+
+        protected Class<?> eventClass;
+        public DebugEventData(Class<?> eventClass) {
+            this.eventClass = eventClass;
+        }
+
+        public boolean shouldCheckEvent(Event event) {
+            return this.eventClass.isAssignableFrom(event.getClass());
+        }
+
+        // is given event's data identical with data stored in this object
+        abstract public boolean checkEvent(Event event);
+    }
+
+    /*
+     * debug information about monitor event
+     */
+    static abstract class DebugMonitorEventData extends DebugEventData {
+        protected ObjectReference monitor;
+
+        protected ThreadReference thread;
+
+        public DebugMonitorEventData(Class<?> eventClass, ObjectReference debuggeeMirror) {
+            super(eventClass);
+
+            this.eventClass = eventClass;
+            monitor = (ObjectReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("monitor"));
+            thread = (ThreadReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("thread"));
+        }
+
+        public String toString() {
+            return eventClass.getName() + " monitor: " + monitor + " thread: " + thread;
+        }
+    }
+
+    /*
+     * information about MonitorContendedEnterEvent
+     */
+    static class DebugMonitorEnterEventData extends DebugMonitorEventData {
+        public DebugMonitorEnterEventData(ObjectReference debuggeeMirror) {
+            super(MonitorContendedEnterEvent.class, debuggeeMirror);
+        }
+
+        public boolean checkEvent(Event event) {
+            MonitorContendedEnterEvent monitorEnterEvent = (MonitorContendedEnterEvent) event;
+
+            return monitorEnterEvent.monitor().equals(monitor) && monitorEnterEvent.thread().equals(thread);
+        }
+    }
+
+    /*
+     * information about MonitorContendedEnteredEvent
+     */
+    static class DebugMonitorEnteredEventData extends DebugMonitorEventData {
+        public DebugMonitorEnteredEventData(ObjectReference debuggeeMirror) {
+            super(MonitorContendedEnteredEvent.class, debuggeeMirror);
+        }
+
+        public boolean checkEvent(Event event) {
+            MonitorContendedEnteredEvent monitorEnterEvent = (MonitorContendedEnteredEvent) event;
+
+            return monitorEnterEvent.monitor().equals(monitor) && monitorEnterEvent.thread().equals(thread);
+        }
+    }
+
+    /*
+     * information about MonitorWaitEvent
+     */
+    static class DebugMonitorWaitEventData extends DebugMonitorEventData {
+        private long timeout;
+
+        public DebugMonitorWaitEventData(ObjectReference debuggeeMirror) {
+            super(MonitorWaitEvent.class, debuggeeMirror);
+
+            timeout = ((LongValue) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("timeout"))).longValue();
+        }
+
+        public boolean checkEvent(Event event) {
+            MonitorWaitEvent monitorWaitEvent = (MonitorWaitEvent) event;
+
+            return monitorWaitEvent.monitor().equals(monitor) && monitorWaitEvent.thread().equals(thread) && (monitorWaitEvent.timeout() == timeout);
+        }
+
+        public String toString() {
+            return eventClass.getName() + " monitor: " + monitor + " thread: " + thread + " timeout: " + timeout;
+        }
+    }
+
+    /*
+     * information about MonitorWaitedEvent
+     */
+    static class DebugMonitorWaitedEventData extends DebugMonitorEventData {
+        private boolean timedout;
+
+        public DebugMonitorWaitedEventData(ObjectReference debuggeeMirror) {
+            super(MonitorWaitedEvent.class, debuggeeMirror);
+
+            timedout = ((BooleanValue) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("timedout"))).booleanValue();
+        }
+
+        public boolean checkEvent(Event event) {
+            MonitorWaitedEvent monitorWaitedEvent = (MonitorWaitedEvent) event;
+
+            return monitorWaitedEvent.monitor().equals(monitor) && monitorWaitedEvent.thread().equals(thread)
+                    && (monitorWaitedEvent.timedout() == timedout);
+        }
+
+        public String toString() {
+            return eventClass.getName() + " monitor: " + monitor + " thread: " + thread + " timedout: " + timedout;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventFilters.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.lang.reflect.*;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import nsk.share.TestBug;
+
+/*
+ * EventFilters class just contain all filter classes
+ */
+public class EventFilters
+{
+    /*
+     * Class is intended for testing event filters.
+     *
+     * Since different request classes have identical methods for adding filters(e.g. addInstanceFilter(),addClassFilter())
+     * but this classes don't have common superclass reflection is used for filter adding.
+     * Subclasses should implement following methods:
+     * - getMethodName(), provide filter adding method's name
+     * - getParametersTypes(), provide filter adding method's parameters types
+     * - getFilterParameters(), provide parameters to be passed in filter adding method
+     *
+     * Also to check is generated event was really filtered subclasses should implement method 'isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)',
+     * this method should check is event generated by given object in given thread accepted by filter.
+     */
+    public abstract static class DebugEventFilter
+    {
+        // eventObject - object which generate event
+        // eventThread - thread where event was generated
+        abstract public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread);
+
+        // call corresponding request's method to set event filter
+        public void addFilter(EventRequest request)
+        throws Throwable
+        {
+            java.lang.reflect.Method method;
+
+            try
+            {
+                method = request.getClass().getMethod(getMethodName(), getParametersTypes());
+            }
+            catch(Exception e)
+            {
+                throw new TestBug("Can't get method '" + getMethodName() + "'");
+            }
+
+            try
+            {
+                method.setAccessible(true);
+                method.invoke(request, getFilterParameters());
+            }
+            catch(IllegalAccessException e)
+            {
+                TestBug testBug = new TestBug("Can't call method '" + getMethodName() + "'");
+                testBug.initCause(e);
+                throw testBug;
+            }
+            catch(InvocationTargetException e)
+            {
+                throw e.getCause();
+            }
+        }
+
+        public boolean isSupported(VirtualMachine vm)
+        {
+            return true;
+        }
+
+        abstract protected String getMethodName();
+        abstract protected Class[] getParametersTypes();
+        abstract protected Object[] getFilterParameters();
+    }
+
+    /*
+     * Restricts the events to those whose method is in a class whose name matches this
+     * restricted regular expression. Only simple regular expressions that begin with '*' or end with '*' are supported
+     */
+    public static class ClassFilter
+    extends DebugEventFilter
+    {
+        protected String classPattern;
+
+        private String startsWithPattern;
+        private String endsWithPattern;
+
+        public ClassFilter(String classPattern)
+        {
+            this.classPattern = classPattern;
+
+            if(classPattern.startsWith("*"))
+                endsWithPattern = classPattern.substring(1);
+            else
+                if(classPattern.endsWith("*"))
+                    startsWithPattern = classPattern.substring(0, classPattern.length() - 1);
+        }
+
+        public String toString()
+        {
+            return "ClassFilter: classes should match pattern: " + classPattern;
+        }
+
+        protected String getMethodName()
+        {
+            return "addClassFilter";
+        }
+
+        protected Class[] getParametersTypes()
+        {
+            return new Class[]{String.class};
+        }
+
+        protected Object[] getFilterParameters()
+        {
+            return new Object[]{classPattern};
+        }
+
+        public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)
+        {
+            if(!isNameMatch(eventObject.referenceType().name()))
+                return false;
+            else
+                return true;
+        }
+
+        protected boolean isNameMatch(String className)
+        {
+            if(startsWithPattern != null)
+                return className.startsWith(startsWithPattern);
+            else
+                if(endsWithPattern != null)
+                    return className.endsWith(endsWithPattern);
+                else
+                    return className.equals(classPattern);
+        }
+    }
+
+    /*
+     * Restricts the events to those whose method is in a class whose name doesn't matches
+     * restricted regular expression. Only simple regular expressions that begin with '*' or end with '*' are supported
+     */
+    public static class ClassExclusionFilter
+    extends ClassFilter
+    {
+        public ClassExclusionFilter(String classPattern)
+        {
+            super(classPattern);
+        }
+
+        public String toString()
+        {
+            return "ClassExclusionFilter: classes match follows pattern should be excluded: " + classPattern;
+        }
+
+        protected String getMethodName()
+        {
+            return "addClassExclusionFilter";
+        }
+
+        public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)
+        {
+            if(isNameMatch(eventObject.referenceType().name()))
+                return false;
+            else
+                return true;
+        }
+    }
+
+    /*
+     * Restricts the events to those whose method is in the given reference type or any of its subtypes
+     */
+    public static class ClassReferenceFilter
+    extends DebugEventFilter
+    {
+        private Class<?> filterClass;
+        private ReferenceType referenceType;
+
+        public ClassReferenceFilter(ReferenceType referenceType)
+        {
+            this.referenceType = referenceType;
+            filterClass = findClass(referenceType);
+        }
+
+        public String toString()
+        {
+            return "ClassReferenceFilter: expect only " + filterClass.getName() + " and its subclasses";
+        }
+
+        protected String getMethodName()
+        {
+            return "addClassFilter";
+        }
+
+        protected Class[] getParametersTypes()
+        {
+            return new Class[]{ReferenceType.class};
+        }
+
+        protected Object[] getFilterParameters()
+        {
+            return new Object[]{referenceType};
+        }
+
+        public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)
+        {
+            Class<?> eventObjectClass = findClass(eventObject.referenceType());
+
+            if(!filterClass.isAssignableFrom(eventObjectClass))
+                return false;
+            else
+                return true;
+        }
+
+        // find class represented by given referenceType
+        private Class<?> findClass(ReferenceType referenceType)
+        {
+            try
+            {
+                return Class.forName(referenceType.name());
+            }
+            catch(ClassNotFoundException e)
+            {
+                throw new TestBug("Can't find class: " + referenceType.name());
+            }
+        }
+    }
+
+    /*
+     * Restricts the events to those in which the currently executing instance ("this") is the given object
+     */
+    public static class ObjectReferenceFilter
+    extends DebugEventFilter
+    {
+        private ObjectReference objectReference;
+
+        public ObjectReferenceFilter(ObjectReference objectReference)
+        {
+            this.objectReference = objectReference;
+        }
+
+        public String toString()
+        {
+            return "ObjectReferenceFilter: expect only object " + objectReference;
+        }
+
+        protected String getMethodName()
+        {
+            return "addInstanceFilter";
+        }
+
+        protected Class[] getParametersTypes()
+        {
+            return new Class[]{ObjectReference.class};
+        }
+
+        protected Object[] getFilterParameters()
+        {
+            return new Object[]{objectReference};
+        }
+
+        public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)
+        {
+            return objectReference.equals(eventObject);
+        }
+
+        public boolean isSupported(VirtualMachine vm)
+        {
+            return vm.canUseInstanceFilters();
+        }
+    }
+
+    /*
+     * Restricts the events to those in the given thread
+     */
+    public static class ThreadFilter
+    extends DebugEventFilter
+    {
+        private ThreadReference threadReference;
+
+        public ThreadFilter(ThreadReference threadReference)
+        {
+            this.threadReference = threadReference;
+        }
+
+        public String toString()
+        {
+            return "ThreadReferenceFilter: expect only thread " + threadReference;
+        }
+
+        protected String getMethodName()
+        {
+            return "addThreadFilter";
+        }
+
+        protected Class[] getParametersTypes()
+        {
+            return new Class[]{ThreadReference.class};
+        }
+
+        protected Object[] getFilterParameters()
+        {
+            return new Object[]{threadReference};
+        }
+
+        public boolean isObjectMatch(ObjectReference eventObject, ThreadReference eventThread)
+        {
+            return threadReference.equals(eventThread);
+        }
+    }
+
+    public static boolean filtered(Event event) {
+        if (event.toString().contains("VM JFR Buffer Thread"))
+            return true;
+
+        if (event.toString().contains("JFR request timer"))
+            return true;
+
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,569 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import java.util.*;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import nsk.share.*;
+
+/**
+ * This class provides a separate thread for asynchronous listening
+ * to JDI events. All received events are sequentially passed
+ * to event listeners. If current event listener returns true
+ * then the event is considered be processed and it is not passed
+ * to remaining listeners.
+ * <p>
+ * The <code>EventHandler</code> thread runs until <code>VMDisconnectEvent</code>
+ * is received or <code>VMDisconnectionedException</code> is caught.
+ *
+ * @see EventListener
+ */
+public class EventHandler implements Runnable {
+
+    private Debugee debuggee = null;
+    private Log log = null;
+
+    private VirtualMachine vm;
+    private EventRequestManager requestManager;
+    /**
+     * Container for event listeners
+     */
+    private static List<EventListener> listeners = Collections.synchronizedList(new Vector<EventListener>());
+    private Thread listenThread;
+
+    /**
+     * Exit status of the <code>EventHandler</code> thread
+     */
+    private static volatile int status = -1;
+
+    /**
+     * Return an exit status of the <code>EventHandler</code> thread
+     * were the values are:
+     * <li><i>-1</i> - no value
+     * <li><i>0</i> - normal termination
+     * <li><i>1</i> - the thread is still running
+     * <li><i>2</i> - abnormal termination
+     */
+    public static synchronized int getStatus() {
+        return status;
+    }
+
+    /**
+     * Default ExceptionRequest with SUSPEND_EVENT_THREAD to be able
+     * to catch debuggee exceptions and output a message.
+     */
+    private static ExceptionRequest defaultExceptionRequest = null;
+
+    /**
+     * This flag will be set true if event of uncaught exception has been
+     * received.
+     */
+    private static volatile boolean defaultExceptionCaught = false;
+    public static synchronized boolean getExceptionCaught() {
+        return defaultExceptionCaught;
+    }
+
+    /**
+     * This flag will be set true if any event which does not have specific
+     * listener has been received.
+     */
+    private static volatile boolean unexpectedEventCaught = false;
+    public static synchronized boolean unexpectedEventCaught() {
+        return unexpectedEventCaught;
+    }
+
+    /**
+     * This flag shows if debugged VM is connected to debugger.
+     */
+    private static volatile boolean vmDisconnected = false;
+    public static synchronized boolean isDisconnected() {
+        return vmDisconnected;
+    }
+
+    public EventHandler(Debugee debuggee, Log log) {
+        this.listenThread = new Thread(this);
+        this.listenThread.setDaemon(true);
+
+        this.debuggee = debuggee;
+        this.log = log;
+        this.vm = debuggee.VM();
+        this.requestManager = vm.eventRequestManager();
+    }
+
+    private void display(String str) {
+        log.display("EventHandler> " + str);
+    }
+
+    // is EventHandler was interrupted
+    private volatile boolean wasInterrupted;
+
+    public void stopEventHandler() {
+        wasInterrupted = true;
+
+        listenThread.interrupt();
+
+        try {
+            listenThread.join();
+        }
+        catch(InterruptedException e) {
+            throw new TestBug("Unexpected exception: " + e);
+        }
+    }
+    /**
+     * The <code>EventHandler</code> thread keeps running until a VMDisconnectedEvent occurs
+     * or some exception occurs during event processing.
+     */
+    public void run() {
+        synchronized(EventHandler.this) {
+            status = 1; // running
+        }
+        do {
+            try {
+                EventSet set = vm.eventQueue().remove();
+
+                switch (set.suspendPolicy()) {
+                    case EventRequest.SUSPEND_NONE:
+                        display("Received event set with policy = SUSPEND_NONE");
+                        break;
+                    case EventRequest.SUSPEND_ALL:
+                        display("Received event set with policy = SUSPEND_ALL");
+                        break;
+                    case EventRequest.SUSPEND_EVENT_THREAD:
+                        display("Received event set with policy = SUSPEND_EVENT_THREAD");
+                        break;
+                }
+
+                synchronized (listeners) {
+                    synchronized (EventHandler.this) {
+                        for (EventListener listener : listeners) {
+                            // proloque listener for a event set
+                            listener.eventSetReceived(set);
+                        }
+
+                        for (Event event : set) {
+                            // print only event class name here because of Event,toString may cause unexpected exception
+                            display("Event: " + event.getClass().getSimpleName()
+                                    + " req " + event.request());
+                            boolean processed = false;
+                            for (EventListener listener : listeners) {
+                                processed = listener.eventReceived(event);
+
+                                if (processed) {
+                                    if (listener.shouldRemoveListener()) {
+                                        listener.eventSetComplete(set);
+                                        removeListener(listener);
+                                    }
+
+                                    break;
+                                }
+                            }
+                        }
+
+                        for (EventListener listener : listeners) {
+                            // epiloque listener for a event set
+                            listener.eventSetComplete(set);
+                        }
+                    }
+                }
+
+            }
+            catch (Exception e) {
+
+                if(e instanceof InterruptedException) {
+                    if(wasInterrupted)
+                        break;
+                }
+
+                log.complain("Exception occured in eventHandler thread: " + e.getMessage());
+                e.printStackTrace(log.getOutStream());
+                synchronized(EventHandler.this) {
+                    // This will make the waiters such as waitForVMDisconnect
+                    // exit their wait loops.
+                    vmDisconnected = true;
+                    status = 2; // abnormal termination
+                    EventHandler.this.notifyAll();
+                }
+                throw new Failure(e);
+            }
+        } while (!wasInterrupted && !isDisconnected());
+
+        if (unexpectedEventCaught || defaultExceptionCaught) {
+            synchronized(EventHandler.this) {
+                status = 2;
+            }
+        }
+        display("finished");
+    }
+
+
+    /**
+     * This is normally called in the main thread of the test debugger.
+     * It starts up an <code>EventHandler</code> thread that gets events coming in
+     * from the debuggee and distributes them to listeners.
+     */
+    public void startListening() {
+        createDefaultEventRequests();
+        createDefaultListeners();
+        listenThread.start();
+    }
+
+
+    /**
+     * This method sets up default requests.
+     */
+    private void createDefaultEventRequests() {
+        /**
+         * The following request will allow to print a warning if a debuggee gets an
+         * unexpected exception. The unexpected exception will be handled in
+         * the eventReceived method in the default listener created.
+         * If a test case does not want an uncaught exception to cause a
+         * message, it must add new listener for uncaught exception events to
+         * handle them.
+         */
+        defaultExceptionRequest = requestManager.createExceptionRequest(null, false, true);
+        defaultExceptionRequest.enable();
+    }
+
+    /**
+     * This method sets up default listeners.
+     */
+    private void createDefaultListeners() {
+        /**
+         * This listener catches up all unexpected events.
+         *
+         */
+        addListener(
+                new EventListener() {
+                    public boolean eventReceived(Event event) {
+                        log.complain("EventHandler>  Unexpected event: " + event.getClass().getName());
+                        unexpectedEventCaught = true;
+                        return true;
+                    }
+                }
+        );
+
+        /**
+         * This listener catches up VMStart event.
+         */
+        addListener(
+                new EventListener() {
+                    public boolean eventReceived(Event event) {
+                        if (event instanceof  VMStartEvent) {
+                            display("received VMStart");
+                            removeListener(this);
+                            return true;
+                        }
+                        return false;
+                    }
+                }
+        );
+
+        /**
+         * This listener catches up VMDeath event.
+         */
+        addListener(
+                new EventListener() {
+                    public boolean eventReceived(Event event) {
+                        if (event instanceof VMDeathEvent) {
+                            display("receieved VMDeath");
+                            removeListener(this);
+                            return true;
+                        }
+                        return false;
+                    }
+                }
+        );
+
+        /**
+         * This listener catches up <code>VMDisconnectEvent</code>event and
+         * signals <code>EventHandler</code> thread to finish.
+         */
+        addListener(
+                new EventListener() {
+                    public boolean eventReceived(Event event) {
+                        if (event instanceof VMDisconnectEvent ) {
+                            display("receieved VMDisconnect");
+                            synchronized(EventHandler.this) {
+                                vmDisconnected = true;
+                                status = 0; // OK finish
+                                EventHandler.this.notifyAll();
+                                removeListener(this);
+                            }
+                            return true;
+                        }
+                        return false;
+                    }
+                }
+        );
+
+        /**
+         * This listener catches uncaught exceptions and print a message.
+         */
+        addListener( new EventListener() {
+            public boolean eventReceived(Event event) {
+                boolean handled = false;
+
+                if (event instanceof ExceptionEvent &&
+                    defaultExceptionRequest != null &&
+                    defaultExceptionRequest.equals(event.request())) {
+
+                    if (EventFilters.filtered(event) == false) {
+                        log.complain("EventHandler>  Unexpected Debuggee Exception: " +
+                                     (ExceptionEvent)event);
+                        defaultExceptionCaught = true;
+                    }
+
+                    handled = true;
+                    vm.resume();
+                }
+
+                return handled;
+            }
+        }
+        );
+    }
+
+    /**
+     * Add at beginning of the list because we want
+     * the LAST added listener to be FIRST to process
+     * current event.
+     */
+    public void addListener(EventListener listener) {
+        display("Adding listener " + listener);
+        synchronized(listeners) {
+            listeners.add(0, listener);
+        }
+    }
+
+    /**
+     * Removes the listener from the list.
+     */
+    public void removeListener(EventListener listener) {
+        display("Removing listener " + listener);
+        synchronized(listeners) {
+            listeners.remove(listener);
+        }
+    }
+
+
+    /**
+     * Returns an event which is received for any of given requests.
+     */
+    public Event waitForRequestedEvent( final EventRequest[] requests,
+            long timeout,
+            boolean shouldRemoveListeners) {
+        class EventNotification {
+            volatile Event event = null;
+        }
+        final EventNotification en = new EventNotification();
+
+        EventListener listener = new EventListener() {
+            public boolean eventReceived(Event event) {
+                for (int i = 0; i < requests.length; i++) {
+                    EventRequest request = requests[i];
+                    if (!request.isEnabled())
+                        continue;
+                    if (request.equals(event.request())) {
+                        display("waitForRequestedEvent: Received event(" + event + ") for request(" + request + ")");
+                        synchronized (EventHandler.this) {
+                            en.event = event;
+                            EventHandler.this.notifyAll();
+                        }
+                        return true;
+                    }
+                }
+                return false;
+            }
+        };
+        if (shouldRemoveListeners) {
+            display("waitForRequestedEvent: enabling remove of listener " + listener);
+            listener.enableRemovingThisListener();
+        }
+        for (int i = 0; i < requests.length; i++) {
+            requests[i].enable();
+        }
+        addListener(listener);
+
+        try {
+            long timeToFinish = System.currentTimeMillis() + timeout;
+            long timeLeft = timeout;
+            synchronized (EventHandler.this) {
+                display("waitForRequestedEvent: vm.resume called");
+                vm.resume();
+
+                while (!isDisconnected() && en.event == null && timeLeft > 0) {
+                    EventHandler.this.wait(timeLeft);
+                    timeLeft = timeToFinish - System.currentTimeMillis();
+                }
+            }
+        } catch (InterruptedException e) {
+            return null;
+        }
+        if (shouldRemoveListeners && !isDisconnected()) {
+            for (int i = 0; i < requests.length; i++) {
+                requests[i].disable();
+            }
+        }
+        if (en.event == null) {
+            throw new Failure("waitForRequestedEvent: no requested events have been received.");
+        }
+        return en.event;
+    }
+
+    /**
+     * Returns an event set which is received for any of given requests.
+     */
+    public EventSet waitForRequestedEventSet( final EventRequest[] requests,
+            long timeout,
+            boolean shouldRemoveListeners) {
+        class EventNotification {
+            volatile EventSet set = null;
+        }
+        final EventNotification en = new EventNotification();
+
+        EventListener listener = new EventListener() {
+            public void eventSetReceived(EventSet set) {
+
+                EventIterator eventIterator = set.eventIterator();
+
+                while (eventIterator.hasNext()) {
+
+                    Event event = eventIterator.nextEvent();
+
+                    for (int i = 0; i < requests.length; i++) {
+                        EventRequest request = requests[i];
+                        if (!request.isEnabled())
+                            continue;
+
+                        if (request.equals(event.request())) {
+                            display("waitForRequestedEventSet: Received event set for request: " + request);
+                            synchronized (EventHandler.this) {
+                                en.set = set;
+                                EventHandler.this.notifyAll();
+                            }
+                            return;
+                        }
+                    }
+                }
+            }
+
+            public boolean eventReceived(Event event) {
+                return (en.set != null);
+            }
+        };
+
+        if (shouldRemoveListeners) {
+            display("waitForRequestedEventSet: enabling remove of listener " + listener);
+            listener.enableRemovingThisListener();
+        }
+        for (int i = 0; i < requests.length; i++) {
+            requests[i].enable();
+        }
+        addListener(listener);
+
+        try {
+            long timeToFinish = System.currentTimeMillis() + timeout;
+            long timeLeft = timeout;
+            synchronized (EventHandler.this) {
+                display("waitForRequestedEventSet: vm.resume called");
+                vm.resume();
+
+                while (!isDisconnected() && en.set == null && timeLeft > 0) {
+                    EventHandler.this.wait(timeLeft);
+                    timeLeft = timeToFinish - System.currentTimeMillis();
+                }
+            }
+        } catch (InterruptedException e) {
+            return null;
+        }
+        if (shouldRemoveListeners && !isDisconnected()) {
+            for (int i = 0; i < requests.length; i++) {
+                requests[i].disable();
+            }
+        }
+        if (en.set == null) {
+            throw new Failure("waitForRequestedEventSet: no requested events have been received.");
+        }
+        return en.set;
+    }
+
+    public synchronized void waitForVMDisconnect() {
+        display("waitForVMDisconnect");
+        while (!isDisconnected()) {
+            try {
+                wait();
+            } catch (InterruptedException e) {
+            }
+        }
+        display("waitForVMDisconnect: done");
+    }
+
+    /**
+     * This is a superclass for any event listener.
+     */
+    public static class EventListener {
+
+        /**
+         * This flag shows if the listener must be removed
+         * after current event has been processed by
+         * this listener.
+         */
+        volatile boolean shouldRemoveListener = false;
+        public boolean shouldRemoveListener() {
+            return shouldRemoveListener;
+        }
+
+        public void enableRemovingThisListener() {
+            shouldRemoveListener = true;
+        }
+
+        /**
+         * This method will be called by <code>EventHandler</code>
+         * for received event set before any call of <code>eventReceived</code>
+         * method for events contained in this set.
+         */
+        public void eventSetReceived(EventSet set) {}
+
+
+        /**
+         * This method will be called by <code>EventHandler</code>
+         * for received event set after all calls of <code>eventReceived</code>
+         * and event specific methods for all events contained in this set.
+         */
+        public void eventSetComplete(EventSet set) {}
+
+        /**
+         * This method will be called by <code>EventHandler</code>
+         * for any event contained in received event set.
+         *
+         * @return <code>true</code> if event was processed by this
+         *          <code>EventListener<code> or <code>false</code> otherwise.
+         */
+        public boolean eventReceived(Event event) {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/EventTestTemplates.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import nsk.share.Consts;
+import nsk.share.TestBug;
+
+/*
+ * Class contains debugger classes based on JDIEventsDebugger intended for JDI events testing
+ */
+public class EventTestTemplates {
+
+    // how many times rerun test in case when tested events aren't generated
+    static final int MAX_TEST_RUN_NUMBER = 10;
+
+    /*
+     * Method contains common code used by EventFilterTests and StressTestTemplate
+     */
+    static void runTestWithRerunPossibilty(JDIEventsDebugger debugger, Runnable testRunner) {
+        for (int i = 0; i < MAX_TEST_RUN_NUMBER; i++) {
+            testRunner.run();
+
+            /*
+             * If events weren't generated at all but test accepts missing events
+             * try to rerun test (rerun test only if it didn't fail yet)
+             */
+            if (debugger.eventsNotGenerated() && debugger.getSuccess()) {
+                if (i < MAX_TEST_RUN_NUMBER - 1) {
+                    debugger.log.display("\nWARNING: tested events weren't generated at all, trying to rerun test (rerun attempt " + (i + 1) + ")\n");
+                    continue;
+                } else {
+                    debugger.setSuccess(false);
+                    debugger.log.complain("Tested events weren't generated after " + MAX_TEST_RUN_NUMBER + " runs, test FAILED");
+                }
+            } else
+                break;
+        }
+    }
+
+    /*
+     * Debugger class for testing event filters, subclasses should parse command
+     * line and call method JDIEventsDebugger.eventFilterTestTemplate with
+     * required arguments.
+     *
+     * Class handles common for event filter tests parameters:
+     * - debuggee class name (e.g. -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee)
+     * - tested event type (e.g. -eventType MONITOR_CONTENTED_ENTER)
+     */
+    public static abstract class EventFilterTest extends JDIEventsDebugger {
+        protected String debuggeeClassName;
+
+        protected EventType eventType;
+
+        protected String[] doInit(String[] args, PrintStream out) {
+            args = super.doInit(args, out);
+
+            ArrayList<String> standardArgs = new ArrayList<String>();
+
+            for (int i = 0; i < args.length; i++) {
+                if (args[i].equals("-debuggeeClassName") && (i < args.length - 1)) {
+                    debuggeeClassName = args[i + 1];
+                    i++;
+                } else if (args[i].equals("-eventType") && (i < args.length - 1)) {
+                    try {
+                        eventType = EventType.valueOf(args[i + 1]);
+                    } catch (IllegalArgumentException e) {
+                        TestBug testBug = new TestBug("Invalid event type : " + args[i + 1], e);
+                        throw testBug;
+                    }
+                    i++;
+                } else
+                    standardArgs.add(args[i]);
+            }
+
+            if (eventType == null)
+                throw new TestBug("Test requires 'eventType' parameter");
+
+            if (debuggeeClassName == null)
+                throw new TestBug("Test requires 'debuggeeClassName' parameter");
+
+            return standardArgs.toArray(new String[] {});
+        }
+
+        abstract protected int getTestFiltersNumber();
+
+        // This class is required to call runTestWithRerunPossibilty()
+        class FilterTestRunner implements Runnable {
+            private int filterIndex;
+
+            FilterTestRunner(int filterIndex) {
+                this.filterIndex = filterIndex;
+            }
+
+            public void run() {
+                eventFilterTestTemplate(eventType, filterIndex);
+            }
+        }
+
+        public final void doTest() {
+            prepareDebuggee(new EventType[] {eventType});
+
+            int filtersNumber = getTestFiltersNumber();
+
+            if (filtersNumber <= 0)
+                throw new TestBug("Invalid filtersNumber: " + filtersNumber);
+
+            for (int filterIndex = 0; filterIndex < getTestFiltersNumber(); filterIndex++) {
+                runTestWithRerunPossibilty(this, new FilterTestRunner(filterIndex));
+            }
+
+            eventHandler.stopEventHandler();
+            removeDefaultBreakpoint();
+        }
+
+        // can't control events from system libraries, so save events only from nsk packages
+        protected boolean shouldSaveEvent(Event event) {
+            return isEventFromNSK(event);
+        }
+
+        protected String debuggeeClassName() {
+            return debuggeeClassName;
+        }
+    }
+
+    /*
+     * Class for testing class exclusion filter, this filter is added by
+     * request's method addClassExclusionFilter(String classPattern) Expected
+     * command line parameter:
+     * - class patterns which should be passed to adding filter method (e.g. -classPatterns java.*:*.Foo)
+     */
+    public static class ClassExclusionFilterTest extends EventFilterTest {
+        protected String classPatterns[];
+
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new ClassExclusionFilterTest().runIt(argv, out);
+        }
+
+        protected String[] doInit(String[] args, PrintStream out) {
+            args = super.doInit(args, out);
+
+            ArrayList<String> standardArgs = new ArrayList<String>();
+
+            for (int i = 0; i < args.length; i++) {
+                if (args[i].equals("-classPatterns") && (i < args.length - 1)) {
+                    classPatterns = args[i + 1].split(":");
+                    i++;
+                } else
+                    standardArgs.add(args[i]);
+            }
+
+            if (classPatterns == null || classPatterns.length == 0)
+                throw new TestBug("Test requires at least one class name pattern");
+
+            return standardArgs.toArray(new String[] {});
+        }
+
+        protected int getTestFiltersNumber() {
+            return classPatterns.length;
+        }
+
+        protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+            if (testedFilterIndex < 0 || testedFilterIndex >= classPatterns.length)
+                throw new TestBug("Invalid testedFilterIndex: " + testedFilterIndex);
+
+            return new EventFilters.DebugEventFilter[]{new EventFilters.ClassExclusionFilter(classPatterns[testedFilterIndex])};
+        }
+    }
+
+    /*
+     * Subclass of ClassExclusionFilterTest, create ClassFilter instead of
+     * ClassExclusionFilter, this filter is added by request's method
+     * addClassFilter(String classPattern)
+     */
+    public static class ClassFilterTest_ClassName extends ClassExclusionFilterTest {
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new ClassFilterTest_ClassName().runIt(argv, out);
+        }
+
+        protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+            if (testedFilterIndex < 0 || testedFilterIndex >= classPatterns.length)
+                throw new TestBug("Invalid testedFilterIndex: " + testedFilterIndex);
+
+            return new EventFilters.DebugEventFilter[]{new EventFilters.ClassFilter(classPatterns[testedFilterIndex])};
+        }
+    }
+
+    /*
+     * Subclass of ClassExclusionFilterTest, create ClassReferenceFilter instead
+     * of ClassExclusionFilter, this filter is added by request's method
+     * addClassFilter(ReferenceType referenceType)
+     */
+    public static class ClassFilterTest_ReferenceType extends ClassExclusionFilterTest {
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new ClassFilterTest_ReferenceType().runIt(argv, out);
+        }
+
+        protected int getTestFiltersNumber() {
+            return classPatterns.length;
+        }
+
+        protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+            if (testedFilterIndex < 0 || testedFilterIndex >= classPatterns.length)
+                throw new TestBug("Invalid testedFilterIndex: " + testedFilterIndex);
+
+            ReferenceType referenceType = debuggee.classByName(classPatterns[testedFilterIndex]);
+            if (referenceType == null)
+                throw new TestBug("Invalid class name is passed: " + classPatterns[testedFilterIndex]);
+
+            return new EventFilters.DebugEventFilter[]{new EventFilters.ClassReferenceFilter(referenceType)};
+        }
+    }
+
+    /*
+     * Class for testing instance filter, this filter is added by request's
+     * method addInstanceFilter(ObjectReference instance). Class tests 3 following
+     * cases:
+     * - add filter for single object
+     * - add filter for the same object 2 times, expect behavior such as in previous case
+     * - add filter for 2 different objects, so events shouldn't be received
+     */
+    public static class InstanceFilterTest extends EventFilterTest {
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new InstanceFilterTest().runIt(argv, out);
+        }
+
+        protected int getTestFiltersNumber() {
+            return 3;
+        }
+
+        protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+            List<ObjectReference> objects = getEventObjects();
+
+            if (objects.size() < 2) {
+                throw new TestBug("Debuggee didn't create event generating objects");
+            }
+
+            switch (testedFilterIndex) {
+            case 0:
+                // filter for 1 object
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ObjectReferenceFilter(objects.get(0))};
+            case 1:
+                // add 2 filters for the same object
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ObjectReferenceFilter(objects.get(0)),
+                        new EventFilters.ObjectReferenceFilter(objects.get(0))};
+            case 2:
+                // add 2 filters for 2 different objects, so don't expect any event
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ObjectReferenceFilter(objects.get(0)),
+                        new EventFilters.ObjectReferenceFilter(objects.get(1))};
+            default:
+                throw new TestBug("Invalid testedFilterIndex: " + testedFilterIndex);
+            }
+        }
+    }
+
+    /*
+     * Class for testing thread filter, this filter is added by request's method
+     * addThreadFilter(ThreadReference thread). Class test 3 follows cases:
+     * - add filter for single thread
+     * - add filter for the same thread 2 times, expect behavior such as in previous case
+     * - add filter for 2 different threads, so events shouldn't be received
+     */
+    public static class ThreadFilterTest extends EventFilterTest {
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new ThreadFilterTest().runIt(argv, out);
+        }
+
+        protected int getTestFiltersNumber() {
+            return 3;
+        }
+
+        protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+            List<ThreadReference> threads = getEventThreads();
+
+            if (threads.size() < 2) {
+                throw new TestBug("Debuggee didn't create event generating threads");
+            }
+
+            switch (testedFilterIndex) {
+            case 0:
+                // filter for 1 thread
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ThreadFilter(threads.get(0))};
+            case 1:
+                // add 2 filters for the same thread
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ThreadFilter(threads.get(0)),
+                        new EventFilters.ThreadFilter(threads.get(0))};
+            case 2:
+                // add 2 filters for 2 different threads, so don't expect any event
+                return new EventFilters.DebugEventFilter[]{new EventFilters.ThreadFilter(threads.get(0)),
+                        new EventFilters.ThreadFilter(threads.get(1))};
+            default:
+                throw new TestBug("Invalid testedFilterIndex: " + testedFilterIndex);
+            }
+        }
+    }
+
+    /*
+     * Class is intended for stress testing, expected command line parameters:
+     * - debuggee class name (e.g.: -debuggeeClassName nsk.share.jdi.MonitorEventsDebuggee)
+     * - one or more tested event types (e.g.: -eventTypes MONITOR_CONTENTED_ENTER:MONITOR_CONTENTED_ENTERED)
+     * - number of events which should be generated during test execution (e.g.: -eventsNumber 500)
+     * - number of threads which simultaneously generate events (e.g.: -threadsNumber 10)
+     *
+     * Class parses command line and calls method JDIEventsDebugger.stressTestTemplate.
+     */
+    public static class StressTestTemplate extends JDIEventsDebugger {
+        protected String debuggeeClassName;
+
+        protected EventType testedEventTypes[];
+
+        protected int eventsNumber = 1;
+
+        protected int threadsNumber = 1;
+
+        public static void main(String argv[]) {
+            System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+        }
+
+        public static int run(String argv[], PrintStream out) {
+            return new StressTestTemplate().runIt(argv, out);
+        }
+
+        protected String[] doInit(String[] args, PrintStream out) {
+            args = super.doInit(args, out);
+
+            ArrayList<String> standardArgs = new ArrayList<String>();
+
+            for (int i = 0; i < args.length; i++) {
+                if (args[i].equals("-eventsNumber") && (i < args.length - 1)) {
+                    eventsNumber = Integer.parseInt(args[i + 1]);
+
+                    // for this stress test events number is equivalent of iterations
+                    // (don't support 0 value of IterationsFactor)
+                    if (stressOptions.getIterationsFactor() != 0)
+                        eventsNumber *= stressOptions.getIterationsFactor();
+
+                    i++;
+                } else if (args[i].equals("-threadsNumber") && (i < args.length - 1)) {
+                    threadsNumber = Integer.parseInt(args[i + 1]);
+
+                    // if 'threadsNumber' is specified test should take in account stress options
+                    threadsNumber *= stressOptions.getThreadsFactor();
+
+                    i++;
+                } else if (args[i].equals("-debuggeeClassName") && (i < args.length - 1)) {
+                    debuggeeClassName = args[i + 1];
+                    i++;
+                } else if (args[i].equals("-eventTypes") && (i < args.length - 1)) {
+                    String eventTypesNames[] = args[i + 1].split(":");
+                    testedEventTypes = new EventType[eventTypesNames.length];
+                    try {
+                        for (int j = 0; j < eventTypesNames.length; j++)
+                            testedEventTypes[j] = EventType.valueOf(eventTypesNames[j]);
+                    } catch (IllegalArgumentException e) {
+                        throw new TestBug("Invalid event type", e);
+                    }
+
+                    i++;
+                } else
+                    standardArgs.add(args[i]);
+            }
+
+            if (testedEventTypes == null || testedEventTypes.length == 0)
+                throw new TestBug("Test requires 'eventTypes' parameter");
+
+            if (debuggeeClassName == null)
+                throw new TestBug("Test requires 'debuggeeClassName' parameter");
+
+            return standardArgs.toArray(new String[] {});
+        }
+
+        // can't control events from system libraries, so save events only from nsk packages
+        protected boolean shouldSaveEvent(Event event) {
+            return isEventFromNSK(event);
+        }
+
+        protected String debuggeeClassName() {
+            return debuggeeClassName;
+        }
+
+        public void doTest() {
+            prepareDebuggee(testedEventTypes);
+
+            runTestWithRerunPossibilty(this, new Runnable() {
+                public void run() {
+                    stressTestTemplate(testedEventTypes, eventsNumber, threadsNumber);
+                }
+            });
+
+            eventHandler.stopEventHandler();
+            removeDefaultBreakpoint();
+        }
+    }
+
+    static public boolean isEventFromNSK(Event event) {
+        if (event instanceof MonitorContendedEnterEvent) {
+            return ((MonitorContendedEnterEvent) event).location() != null && ((MonitorContendedEnterEvent) event).monitor().type().name().startsWith("nsk.");
+        }
+        if (event instanceof MonitorContendedEnteredEvent) {
+            return ((MonitorContendedEnteredEvent) event).location() != null  && ((MonitorContendedEnteredEvent) event).monitor().type().name().startsWith("nsk.");
+        }
+        if (event instanceof MonitorWaitEvent) {
+            return ((MonitorWaitEvent) event).monitor().type().name().startsWith("nsk.");
+        }
+        if (event instanceof MonitorWaitedEvent) {
+            return ((MonitorWaitedEvent) event).monitor().type().name().startsWith("nsk.");
+        }
+
+        // don't filter other events
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ForceEarlyReturnDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+/*
+ * Class contains methods common for nsk/jdi/ThreadReference/forceEarlyReturn tests
+ */
+public class ForceEarlyReturnDebugger extends TestDebuggerType2 {
+    protected boolean canRunTest() {
+        if (!vm.canForceEarlyReturn()) {
+            log.display("TEST CANCELED due to:  vm.canForceEarlyReturn() = false");
+            return false;
+        } else
+            return super.canRunTest();
+    }
+
+    protected void testMethodExitEvent(ThreadReference thread, String methodName) {
+        testMethodExitEvent(thread, methodName, true);
+    }
+
+    /*
+     * Method for checking is after forceEarlyReturn MethodExitEvent is generated as it would be in a normal return
+     * Before calling this method forceEarlyReturn() should be already called and tested thread should be suspended
+     */
+    protected void testMethodExitEvent(ThreadReference thread, String methodName, boolean resumeThreadAfterEvent) {
+        MethodExitRequest methodExitRequest;
+        methodExitRequest = debuggee.getEventRequestManager().createMethodExitRequest();
+        methodExitRequest.addThreadFilter(thread);
+        methodExitRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+        methodExitRequest.enable();
+
+        EventListenerThread listenerThread = new EventListenerThread(methodExitRequest);
+        listenerThread.start();
+        listenerThread.waitStartListen();
+
+        thread.resume();
+
+        Event event = listenerThread.getEvent();
+
+        if (event == null) {
+            setSuccess(false);
+            log.complain("MethodExitEvent was not generated " + ", method: " + methodName);
+        } else {
+            if (!((MethodExitEvent) event).method().name().equals(methodName)) {
+                setSuccess(false);
+                log.complain("Invalid MethodExitEvent: expected method - " + methodName + ", actually - "
+                        + ((MethodExitEvent) event).method().name());
+            }
+        }
+
+        methodExitRequest.disable();
+        vm.eventRequestManager().deleteEventRequest(methodExitRequest);
+
+        if (resumeThreadAfterEvent)
+            thread.resume();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.Log;
+import nsk.share.ObjectInstancesManager;
+import nsk.share.TestBug;
+import nsk.share.jpda.DebugeeArgumentHandler;
+import nsk.share.jpda.IOPipe;
+
+/*
+ * Debuggee class used in tests for heapwalking(tests for VirtualMachine.instanceCounts, ReferenceType.instances, ObjectReference.referrers).
+ * Handle commands related to creation of objects instances with given reference type
+ * and given referrers number, use for this purposes nsk.share.ObjectInstancesManager.
+ */
+public class HeapwalkingDebuggee extends AbstractJDIDebuggee {
+    protected ObjectInstancesManager objectInstancesManager;
+
+    // reference of this type should be included in ObjectReference.referringObjects
+    public static Set<String> includedIntoReferrersCountTypes = new HashSet<String>();
+
+    // reference of this type should be included in ReferenceType.instances
+    public static Set<String> includedIntoInstancesCountTypes = new HashSet<String>();
+
+    static {
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE);
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE);
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE);
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE);
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_GLOBAL_REFERENCE);
+        includedIntoInstancesCountTypes.add(ObjectInstancesManager.JNI_LOCAL_REFERENCE);
+
+        includedIntoReferrersCountTypes.add(ObjectInstancesManager.STRONG_REFERENCE);
+        includedIntoReferrersCountTypes.add(ObjectInstancesManager.WEAK_REFERENCE);
+        includedIntoReferrersCountTypes.add(ObjectInstancesManager.SOFT_REFERENCE);
+        includedIntoReferrersCountTypes.add(ObjectInstancesManager.PHANTOM_REFERENCE);
+    }
+
+    //create number instance of class with given name, command format: createInstances:class_name:instance_count[:referrer_count:referrer_type]
+    static public final String COMMAND_CREATE_INSTANCES = "createInstances";
+
+    //'delete'(make unreachable) number instance of class with given name, command format: deleteInstances:class_name:instance_count:referrer_count
+    static public final String COMMAND_DELETE_INSTANCES = "deleteInstances";
+
+    //delete number referrers
+    static public final String COMMAND_DELETE_REFERRERS = "deleteReferrers";
+
+    //create instance with all type referrers
+    static public final String COMMAND_CREATE_ALL_TYPE_REFERENCES = "createAllTypeReferences";
+
+    protected void init(String args[]) {
+        super.init(args);
+        objectInstancesManager = new ObjectInstancesManager(log);
+    }
+
+    public void initDebuggee(DebugeeArgumentHandler argHandler, Log log, IOPipe pipe, String args[], boolean callExit) {
+        super.initDebuggee(argHandler, log, pipe, args, callExit);
+        objectInstancesManager = new ObjectInstancesManager(log);
+    }
+
+    public boolean parseCommand(String command) {
+        if (super.parseCommand(command))
+            return true;
+
+        try {
+            StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command));
+            tokenizer.whitespaceChars(':', ':');
+            tokenizer.wordChars('_', '_');
+            tokenizer.wordChars('$', '$');
+            tokenizer.wordChars('[', ']');
+            tokenizer.wordChars('|', '|');
+
+            if (command.startsWith(COMMAND_CREATE_INSTANCES)) {
+                //createInstances:class_name:instance_count[:referrer_count:referrer_type]
+
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int instanceCounts = (int) tokenizer.nval;
+
+                int referrerCount = 1;
+                Set<String> referrerType = new HashSet<String>();
+
+                if (tokenizer.nextToken() == StreamTokenizer.TT_NUMBER) {
+                    referrerCount = (int) tokenizer.nval;
+
+                    if (tokenizer.nextToken() == StreamTokenizer.TT_WORD)
+                        referrerType.addAll(Arrays.asList(tokenizer.sval.split("\\|")));
+                }
+                if (referrerType.isEmpty()) {
+                    referrerType.add(ObjectInstancesManager.STRONG_REFERENCE);
+                }
+
+                objectInstancesManager.createReferences(instanceCounts, className, referrerCount, referrerType);
+
+                return true;
+            } else if (command.startsWith(COMMAND_DELETE_INSTANCES)) {
+                //deleteInstances:class_name:instance_count:referrer_count
+
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int instanceCounts = (int) tokenizer.nval;
+
+                objectInstancesManager.deleteAllReferrers(instanceCounts, className);
+
+                return true;
+            } else if (command.startsWith(COMMAND_DELETE_REFERRERS)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int referrersCount = (int) tokenizer.nval;
+
+                Set<String> referrerTypes = new HashSet<String>();
+                if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
+                    referrerTypes.addAll(Arrays.asList(tokenizer.sval.split("\\|")));
+                }
+
+                objectInstancesManager.deleteReferrers(className, referrersCount, referrerTypes);
+
+                return true;
+            } else if (command.startsWith(COMMAND_CREATE_ALL_TYPE_REFERENCES)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int instanceCounts = (int) tokenizer.nval;
+
+                objectInstancesManager.createAllTypeReferences(className, instanceCounts);
+
+                return true;
+            }
+        } catch (IOException e) {
+            throw new TestBug("Invalid command format: " + command);
+        }
+
+        return false;
+    }
+
+    // instances of some classes couldn't be strictly controlled during test execution, use non-strict checks for this classes
+    public static boolean useStrictCheck(String className, boolean otherThreadPresent) {
+        if (className.equals("java.lang.String"))
+            return false;
+
+        if (className.equals("char[]"))
+            return false;
+
+        if (className.equals("byte[]"))
+            return false;
+
+        if (className.equals("java.lang.Thread")) {
+            if (otherThreadPresent)
+                return false;
+        }
+
+        return true;
+    }
+
+    // is reference with given type should be included in ObjectReference.referringObjects
+    static public boolean isIncludedIntoReferrersCount(String referenceType) {
+        if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) {
+            throw new TestBug("Invalid reference type: " + referenceType);
+        }
+
+        return includedIntoReferrersCountTypes.contains(referenceType);
+    }
+
+    // is reference with given type should be included in ReferenceType.instances
+    static public boolean isIncludedIntoInstancesCount(String referenceType) {
+        if (!ObjectInstancesManager.allReferenceTypes.contains(referenceType)) {
+            throw new TestBug("Invalid reference type: " + referenceType);
+        }
+
+        return includedIntoInstancesCountTypes.contains(referenceType);
+    }
+
+    public static void main(String args[]) {
+        HeapwalkingDebuggee debuggee = new HeapwalkingDebuggee();
+        debuggee.init(args);
+        debuggee.doTest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/HeapwalkingDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.util.*;
+import com.sun.jdi.*;
+import nsk.share.TestBug;
+
+/*
+ * Debugger class used in tests for heapwalking(tests for VirtualMachine.instanceCounts, ReferenceType.instances, ObjectReference.referrers)
+ * Contains several common checking and auxiliary methods.
+ */
+public class HeapwalkingDebugger extends TestDebuggerType2 {
+    // instances of some classes couldn't be strictly controlled during test execution, use non-strict checks for this classes
+    protected boolean strictCheck(String className) {
+        boolean otherThreadPresent = isJFR_active();
+        return HeapwalkingDebuggee.useStrictCheck(className, otherThreadPresent);
+    }
+
+    // wrapper for VirtualMachine.instanceCounts
+    public long getInstanceCount(String className) {
+        List<ReferenceType> list = vm.classesByName(className);
+
+        if (list.size() == 0)
+            return 0;
+
+        if (list.size() > 1) {
+            setSuccess(false);
+            log.complain("Unexpected collection size returned by VirtualMachine.classesByName(" + className + "): " + list.size()
+                    + ", only 1 entry was expected.");
+        }
+
+        long result[] = (vm.instanceCounts(list));
+
+        return result[0];
+    }
+
+    // tests that vm.instanceCounts(vm.allClasses()) doesn't throws any exceptions
+    protected void testInstanceCounts() {
+        try {
+            vm.instanceCounts(vm.allClasses());
+        } catch (Throwable t) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + t);
+            t.printStackTrace(log.getOutStream());
+        }
+
+    }
+
+    // check size of list returned by ReferenceType.instances
+    protected void checkDebugeeAnswer_instances(String className, int expectedCount) {
+        ReferenceType referenceType = debuggee.classByName(className);
+
+        int instanceCounts = referenceType.instances(0).size();
+
+        if (strictCheck(className)) {
+            if (referenceType.instances(0).size() != expectedCount) {
+                setSuccess(false);
+                log.complain("Unexpected size of referenceType.instances(" + className + "): " + instanceCounts + ", expected: " + expectedCount);
+            }
+        } else {
+            if (referenceType.instances(0).size() < expectedCount) {
+                setSuccess(false);
+                log.complain("Unexpected size of referenceType.instances(" + className + "): " + instanceCounts + ", expected: >= " + expectedCount);
+            }
+        }
+    }
+
+    // check value returned by VirtualMachine.instanceCounts,
+    // note that method call method isDebuggeeReady() which check that debuggee completed pervious command and is ready for new one
+    public void checkDebugeeAnswer_instanceCounts(String className, int expectedValue) {
+        if (!isDebuggeeReady())
+            return;
+
+        try {
+            long instanceCounts = getInstanceCount(className);
+
+            if (strictCheck(className)) {
+                if (instanceCounts != expectedValue) {
+                    setSuccess(false);
+                    log.complain("Wrong value was returned  by VirtualMachine.instanceCounts(" + className + "): " + instanceCounts + ", expected: "
+                            + expectedValue);
+                }
+            } else {
+                if (instanceCounts < expectedValue) {
+                    setSuccess(false);
+                    log.complain("Wrong value was returned  by VirtualMachine.instanceCounts(" + className + "): " + instanceCounts
+                            + ", expected: >= " + expectedValue);
+                }
+            }
+        } catch (Throwable e) {
+            setSuccess(false);
+
+            log.complain("Unexpected exception when getting instance count info:");
+            e.printStackTrace(log.getOutStream());
+        }
+    }
+
+    // Verifies number of instances of a class.
+    // Two types of checks are done:
+    //   1. Current instances >= old instances + created instances.
+    //   2. New instances >= created instances.
+    //
+    // The check in case 1 can only be done for classes where the test controls
+    // all created and deleted instances.
+    // Other classes, like java.lang.String, can not make this check since
+    // an instance in "old instances" may have been removed by a GC.
+    // In that case the tetst would fail because it finds too few current instances.
+    public void checkDebugeeAnswer_instanceCounts(String className, int countCreated, List<ObjectReference> oldReferences) {
+        if (strictCheck(className)) {
+            int countAll = countCreated + oldReferences.size();
+            checkDebugeeAnswer_instanceCounts(className, countAll);
+            checkDebugeeAnswer_instances(className, countAll);
+        } else {
+            // isDebuggeeReady() check is hidden in checkDebugeeAnswer_instanceCounts() above.
+            // Must call it separately if we don't call checkDebugeeAnswer_instanceCounts().
+            if (!isDebuggeeReady()) {
+                return;
+            }
+        }
+
+        // Verify number of new instances created.
+        int countFoundCreated = countNewInstances(className, oldReferences);
+        if (countFoundCreated < countCreated) {
+            setSuccess(false);
+            log.complain("Too few new instances(" + className + "). Expected >= " + countCreated + ", found " + countFoundCreated);
+        }
+    }
+
+    private int countNewInstances(String className, List<ObjectReference> oldReferences) {
+        // New references = current references - old references.
+        List<ObjectReference> newReferences = new ArrayList<ObjectReference>(getObjectReferences(className, vm));
+        newReferences.removeAll(oldReferences);
+        return newReferences.size();
+    }
+
+    // check value returned by InterfaceType.instances
+    protected void checkDebugeeAnswer_InterfaceType_instances(InterfaceType interfaceType, int expectedInstances) {
+        int instanceCounts = interfaceType.instances(0).size();
+
+        if (instanceCounts != expectedInstances) {
+            setSuccess(false);
+            log.complain("List with wrong size was returned by InterfaceType.instances(" + interfaceType.name() + "): " + instanceCounts
+                         + ", expected: " + expectedInstances);
+        }
+    }
+
+    static public List<ObjectReference> filterObjectReferrence(List<ObjectReference> objectsToFilter, List<ObjectReference> sourceList) {
+        List<ObjectReference> result = new ArrayList<ObjectReference>();
+
+        for (ObjectReference object : sourceList) {
+            if (!objectsToFilter.contains(object))
+                result.add(object);
+        }
+
+        return result;
+    }
+
+    static public List<ObjectReference> getObjectReferences(String className, VirtualMachine vm) {
+        List<ReferenceType> referenceTypes = vm.classesByName(className);
+
+        List<ObjectReference> objectReferences;
+
+        if (referenceTypes.size() == 0)
+            objectReferences = new ArrayList<ObjectReference>();
+        else if (referenceTypes.size() == 1)
+            objectReferences = referenceTypes.get(0).instances(0);
+        else {
+            throw new TestBug("Unexpected collection size returned by VirtualMachine.classesByName: " + referenceTypes.size()
+                    + ", only 1 entry was expected.");
+        }
+
+        return objectReferences;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIEventsDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.TestBug;
+
+/*
+ *  Subclasses of this class generate events and if needed
+ *  save debug information about generated events
+ */
+abstract class EventActionsExecutor {
+    // should this event generator save information about generated events
+    public boolean saveEventData;
+
+    // information about generated events(this data available for debugger)
+    public List<DebuggeeEventData.DebugEventData> debugEventDataList = new ArrayList<DebuggeeEventData.DebugEventData>();
+
+    public abstract void doEventAction();
+
+    protected void addEventData(DebuggeeEventData.DebugEventData eventData) {
+        if (saveEventData)
+            debugEventDataList.add(eventData);
+    }
+
+    public void clearDebugData() {
+        debugEventDataList.clear();
+    }
+}
+
+/*
+ * Class handles commands for running given number of threads which generate
+ * given events. Objects which generate events save information about generated
+ * events and this data available for debugger
+ *
+ * Class was written to test monitor evens(MonitorWaitEvent, MonitorWaitedEvent,
+ * MonitorContendedEnterEvent, MonitorContendedEnteredEvent), possible it can be
+ * used in tests for other events
+ */
+abstract public class JDIEventsDebuggee extends AbstractJDIDebuggee {
+    protected String[] doInit(String[] args) {
+        Thread.currentThread().setName(MAIN_THREAD_NAME);
+        return super.doInit(args);
+    }
+
+    public static final String MAIN_THREAD_NAME = "JDIEventsDebuggee_MainThread";
+
+    // command:events_count:event types
+    public static final String COMMAND_CREATE_ACTIONS_EXECUTORS = "createActionsExecutors";
+
+    // command
+    public static final String COMMAND_START_EXECUTION = "startExecution";
+
+    // command
+    public static final String COMMAND_WAIT_EXECUTION_COMPLETION = "waitExecutionCompletion";
+
+    // command
+    public static final String COMMAND_STOP_EXECUTION = "stopExecution";
+
+    protected List<EventActionsThread> eventActionsExecutorsPool = new ArrayList<EventActionsThread>();
+
+    // initialize with empty array
+    public static DebuggeeEventData.DebugEventData generatedEvents[] = new DebuggeeEventData.DebugEventData[0];
+
+    // debuggee's main thread also can generate events and information about
+    // this events should be saved (like for event generators)
+    protected boolean saveEventData;
+
+    public boolean parseCommand(String command) {
+        if (super.parseCommand(command))
+            return true;
+
+        StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(
+                command));
+        tokenizer.whitespaceChars(':', ':');
+        tokenizer.wordChars('_', '_');
+        tokenizer.wordChars(' ', ' ');
+
+        try {
+            if (command.startsWith(COMMAND_CREATE_ACTIONS_EXECUTORS)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int eventsCount = (int) tokenizer.nval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                // pass to the createActionsExecutors() string describing types
+                // of tested events
+                createActionsExecutors(tokenizer.sval, eventsCount);
+
+                return true;
+            } else if (command.equals(COMMAND_START_EXECUTION)) {
+                startExecution();
+
+                return true;
+            } else if (command.equals(COMMAND_WAIT_EXECUTION_COMPLETION)) {
+                if (executionControllingThread == null)
+                    throw new TestBug("executionControllingThread wasn't started");
+
+                try {
+                    executionControllingThread.join();
+                    executionControllingThread = null;
+                } catch (InterruptedException e) {
+                    unexpectedException(e);
+                }
+
+                return true;
+            } else if (command.equals(COMMAND_STOP_EXECUTION)) {
+                if (executionControllingThread == null)
+                    throw new TestBug("executionControllingThread wasn't started");
+
+                for (EventActionsThread thread : eventActionsExecutorsPool) {
+                    thread.stopExecution();
+                }
+
+                return true;
+            }
+
+        } catch (IOException e) {
+            throw new TestBug("Invalid command format: " + command);
+        }
+
+        return false;
+    }
+
+    // debugee waits completion of test threads in separate thread to free thread listening commands
+    protected Thread executionControllingThread;
+
+    protected void startExecution() {
+        if (eventActionsExecutorsPool.size() == 0) {
+            throw new TestBug("ActionsExecutors were not created");
+        }
+
+        for (EventActionsThread thread : eventActionsExecutorsPool) {
+            thread.startExecution();
+        }
+
+        // debugee waits completion of test threads in separate thread to free thread listening commands
+        executionControllingThread = new Thread(
+                new Runnable() {
+                    public void run() {
+                        for (EventActionsThread thread : eventActionsExecutorsPool) {
+                            try {
+                                thread.join();
+                            } catch (InterruptedException e) {
+                                unexpectedException(e);
+                            }
+                        }
+
+                        completeExecution();
+                    }
+                });
+
+        executionControllingThread.start();
+    }
+
+    protected void completeExecution() {
+        // save information about all generated events in array 'generatedEvents'
+        List<DebuggeeEventData.DebugEventData> generatedEventsList = new ArrayList<DebuggeeEventData.DebugEventData>();
+
+        for (EventActionsThread thread : eventActionsExecutorsPool)
+            generatedEventsList.addAll(thread.executor.debugEventDataList);
+
+        generatedEvents = generatedEventsList.toArray(new DebuggeeEventData.DebugEventData[]{});
+
+        // stop at breakpoint when all events was generated
+        breakpointMethod();
+
+        // clear data about generated events to allow execute command
+        // several times
+        clearResults();
+    }
+
+    // clear data about generated events to allow execute test several times
+    protected void clearResults() {
+        for (EventActionsThread thread : eventActionsExecutorsPool)
+            thread.executor.clearDebugData();
+
+        eventActionsExecutorsPool.clear();
+
+        generatedEvents = new DebuggeeEventData.DebugEventData[0];
+    }
+
+    // create threads generating events
+    abstract protected void createActionsExecutors(String description,
+            int eventsCount);
+
+    /*
+     * Thread generating events, call in loop
+     * EventActionsExecutor.doEventAction()
+     */
+    static class EventActionsThread extends Thread {
+        // how many times call executor.doMonitorAction()
+        private int actionsNumber;
+
+        // object generating events
+        public EventActionsExecutor executor;
+
+        public EventActionsThread(EventActionsExecutor executor,
+                int actionsNumber) {
+            this.actionsNumber = actionsNumber;
+            this.executor = executor;
+        }
+
+        private volatile boolean startExecution;
+        private volatile boolean stopExecution;
+
+        public void run() {
+            while (!startExecution)
+                yield();
+
+            for (int i = 0; (i < actionsNumber) && !stopExecution; i++)
+                executor.doEventAction();
+        }
+
+        public void startExecution() {
+            startExecution = true;
+        }
+
+        public void stopExecution() {
+            stopExecution = true;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/JDIEventsDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,909 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.PrintStream;
+import java.lang.reflect.*;
+import java.util.*;
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import nsk.share.TestBug;
+
+/*
+ *  Class is used as base debugger in tests for following events and event requests:
+ *  - MonitorContendedEnterRequest / MonitorContendedEnterEvent
+ *  - MonitorContendedEnteredRequest / MonitorContendedEnteredEvent
+ *  - MonitorWaitRequest / MonitorWaitEvent
+ *  - MonitorWaitedRequest / MonitorWaitedEvent
+ *
+ * In all these tests similar scenario is used:
+ *  - debugger VM forces debuggee VM to create number of objects which should generate events during test
+ *  - if any event filters are used each generating event object is checked is this object accepted by all filters,
+ *    if object was accepted it should save information about all generated events and this information is available for debugger
+ * - debuggee performs event generation and stop at breakpoint
+ * - debugger reads data saved by event generators and checks is only expected events was generated
+ */
+public class JDIEventsDebugger extends TestDebuggerType2 {
+    // types of tested events
+    static public enum EventType {
+        MONITOR_CONTENTED_ENTER,
+        MONITOR_CONTENTED_ENTERED,
+        MONITOR_WAIT,
+        MONITOR_WAITED
+    }
+
+    /*
+     * Class contains information required for event testing
+     */
+    static class TestedEventData {
+        // event class
+        public Class<?> eventClass;
+
+        // class representing event data on debuggee's side
+        public Class<?> eventDataMirrorClass;
+
+        // class representing event data on debugger's side
+        public Class<?> eventDataClass;
+
+        public TestedEventData(Class<?> eventClass, Class<?> eventDataMirrorClass, Class<?> eventDataClass) {
+            this.eventClass = eventClass;
+            this.eventDataMirrorClass = eventDataMirrorClass;
+            this.eventDataClass = eventDataClass;
+        }
+    }
+
+    static public Map<EventType, TestedEventData> testedEventData = new HashMap<EventType, TestedEventData>();
+
+    static {
+        testedEventData.put(EventType.MONITOR_CONTENTED_ENTER, new TestedEventData(MonitorContendedEnterEvent.class,
+                DebuggeeEventData.DebugMonitorEnterEventData.class, DebuggerEventData.DebugMonitorEnterEventData.class));
+
+        testedEventData.put(EventType.MONITOR_CONTENTED_ENTERED, new TestedEventData(MonitorContendedEnteredEvent.class,
+                DebuggeeEventData.DebugMonitorEnteredEventData.class, DebuggerEventData.DebugMonitorEnteredEventData.class));
+
+        testedEventData.put(EventType.MONITOR_WAIT, new TestedEventData(MonitorWaitEvent.class, DebuggeeEventData.DebugMonitorWaitEventData.class,
+                DebuggerEventData.DebugMonitorWaitEventData.class));
+
+        testedEventData.put(EventType.MONITOR_WAITED, new TestedEventData(MonitorWaitedEvent.class,
+                DebuggeeEventData.DebugMonitorWaitedEventData.class, DebuggerEventData.DebugMonitorWaitedEventData.class));
+    }
+
+    static public TestedEventData[] eventDataByEventTypes(EventType[] eventTypes) {
+        TestedEventData[] result = new TestedEventData[eventTypes.length];
+
+        int i = 0;
+        for (EventType eventType : eventTypes) {
+            TestedEventData eventData = testedEventData.get(eventType);
+
+            if (eventData == null)
+                throw new TestBug("Unsupported event type: " + eventType);
+
+            result[i++] = eventData;
+        }
+
+        return result;
+    }
+
+    /*
+     * Dummy event listener, just accepts all events
+     */
+    public class DummyEventListener extends EventHandler.EventListener {
+        private volatile boolean breakpointEventReceived;
+
+        public boolean eventReceived(Event event) {
+            if (event instanceof BreakpointEvent) {
+                breakpointEventReceived = true;
+                vm.resume();
+            }
+
+            return true;
+        }
+
+        public void waitBreakpoint() {
+            while (!breakpointEventReceived)
+                Thread.yield();
+        }
+    }
+
+    /*
+     * Parse common for event tests parameters
+     */
+    protected String[] doInit(String[] args, PrintStream out) {
+        args = super.doInit(args, out);
+
+        ArrayList<String> standardArgs = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-allowExtraEvents")) {
+                extraEventClasses = createEventClassArray(args[i + 1]);
+
+                i++;
+            } else if (args[i].equals("-allowMissedEvents")) {
+                missedEventClasses = createEventClassArray(args[i + 1]);
+
+                i++;
+            } else
+                standardArgs.add(args[i]);
+        }
+
+        return standardArgs.toArray(new String[standardArgs.size()]);
+    }
+
+    // can't control some kinds of events (events from system libraries) and
+    // not all events should be saved for analysis
+    // (should be implemented in subclasses)
+    protected boolean shouldSaveEvent(Event event) {
+        return true;
+    }
+
+    public Class<?> findEventDataClass(TestedEventData[] testedEventData, Event event) {
+        for (TestedEventData eventData : testedEventData) {
+            if (eventData.eventClass.isAssignableFrom(event.getClass()))
+                return eventData.eventClass;
+        }
+
+        return null;
+    }
+
+    /*
+     * This event listener stores received monitor events until BreakpointEvent
+     * is not received, after getting of BreakpointEvent checks only expected
+     * events were received
+     */
+    public class EventListener extends EventHandler.EventListener {
+
+        private TestedEventData[] testedEventData;
+
+        public EventListener(TestedEventData[] testedEventData) {
+            this.testedEventData = testedEventData;
+        }
+
+        private boolean shouldHandleEvent(Event event) {
+            return findEventDataClass(testedEventData, event) == null ? false : true;
+        }
+
+        volatile boolean breakpointWasReceived;
+
+        // execution was interrupted because of timeout
+        volatile boolean executionWasInterrupted;
+
+        public boolean eventReceived(Event event) {
+            if (shouldHandleEvent(event)) {
+                if (shouldSaveEvent(event)) {
+
+                    Class<?> eventClass;
+
+                    eventClass = findEventDataClass(testedEventData, event);
+                    List<Event> events = allReceivedEvents.get(eventClass);
+
+                    if (events == null) {
+                        events = new LinkedList<Event>();
+                        allReceivedEvents.put(eventClass, events);
+                    }
+
+                    events.add(event);
+                }
+
+                return true;
+            }
+            // debuggee should stop at the end of test
+            else if (event instanceof BreakpointEvent) {
+                breakpointWasReceived = true;
+
+                try {
+                    // if execution was interrupted because of timeout don't check received
+                    // events because it can consume too much time
+                    if (!executionWasInterrupted) {
+                        // get data from debuggee about all generated events
+                        initExpectedEvents(testedEventData);
+
+                        checkEvents();
+                    } else
+                        log.complain("WARNING: execution was interrupted because of timeout, test doesn't check received events");
+                } catch (Throwable t) {
+                    unexpectedException(t);
+                }
+
+                vm.resume();
+
+                return true;
+            }
+
+            return false;
+        }
+    }
+
+    protected Class<?> extraEventClasses[];
+
+    protected Class<?> missedEventClasses[];
+
+    /*
+     * If test can't strictly control event generation it may allow generation
+     * of extra events and unexpected events aren't treated as error
+     * (subclasses should specify what kinds of extra events are allowed)
+     */
+    private Class<?>[] allowedExtraEvents() {
+        return extraEventClasses;
+    }
+
+    /*
+     * If test can't strictly control event generation case when debugger doesn't
+     * receive expected event may be not treated as failure
+     * (subclasses should specify what kinds of expected events can be not received)
+     */
+    private Class<?>[] allowedMissedEvents() {
+        return missedEventClasses;
+    }
+
+    private boolean isExtraEventAllowed(Class<?> eventClass) {
+        return checkEvent(eventClass, allowedExtraEvents());
+    }
+
+    private boolean isMissedEventAllowed(Class<?> eventClass) {
+        return checkEvent(eventClass, allowedMissedEvents());
+    }
+
+    private boolean checkEvent(Class<?> eventClass, Class<?> classes[]) {
+        if (classes == null)
+            return false;
+
+        for (Class<?> klass : classes) {
+            if (klass.isAssignableFrom(eventClass))
+                return true;
+        }
+
+        return false;
+    }
+
+    // flag is modified from the event listener thread
+    private volatile boolean eventsNotGenerated;
+
+    /*
+     * Method returns true if test expects event generation, but events weren't
+     * generated. If test can't strictly control event generation such case isn't
+     * necessarily treated as test failure (sublasses of JDIEventsDebugger can
+     * for example try to rerun test several times).
+     */
+    protected boolean eventsNotGenerated() {
+        return eventsNotGenerated;
+    }
+
+    /*
+     * Print debug information about expected and received events(this data
+     * should be stored in lists 'allExpectedEvents' and 'allReceivedEvents')
+     * and check that only expected events were received
+     */
+    private void checkEvents() {
+        if (getAllExpectedEvents().size() > 0 && getAllReceivedEvents().size() == 0 && allowedMissedEvents() != null) {
+            log.display("WARNING: didn't receive any event");
+            eventsNotGenerated = true;
+        }
+
+        log.display("ALL RECEIVED EVENTS: ");
+        for (Event event : getAllReceivedEvents())
+            log.display("received event: " + eventToString(event));
+
+        log.display("ALL EXPECTED EVENTS: ");
+        for (DebuggerEventData.DebugEventData eventData : getAllExpectedEvents())
+            log.display("expected event: " + eventData);
+
+        // try to find received event in the list of expected events, if this event
+        // was found remove data about events from both lists
+        for (Class<?> eventClass : allReceivedEvents.keySet()) {
+            List<Event> receivedEvents = allReceivedEvents.get(eventClass);
+            List<DebuggerEventData.DebugEventData> expectedEvents = allExpectedEvents.get(eventClass);
+
+            for (Iterator<Event> allReceivedEventsIterator = receivedEvents.iterator();
+                allReceivedEventsIterator.hasNext();) {
+
+                Event event = allReceivedEventsIterator.next();
+
+                for (Iterator<DebuggerEventData.DebugEventData> allExpectedEventsIterator = expectedEvents.iterator();
+                    allExpectedEventsIterator.hasNext();) {
+
+                    DebuggerEventData.DebugEventData debugEventData = allExpectedEventsIterator.next();
+
+                    if (debugEventData.shouldCheckEvent(event)) {
+                        if (debugEventData.checkEvent(event)) {
+                            allExpectedEventsIterator.remove();
+                            allReceivedEventsIterator.remove();
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        List<Event> receivedEventsLeft = getAllReceivedEvents();
+
+        // check is all received events were found in expected
+        if (receivedEventsLeft.size() > 0) {
+            // if allowExtraEvents = true extra events are not treated as error
+            for (Event event : receivedEventsLeft) {
+                if (!isExtraEventAllowed(event.getClass())) {
+                    setSuccess(false);
+                    log.complain("Unexpected event " + eventToString(event));
+                }
+            }
+        }
+
+        List<DebuggerEventData.DebugEventData> expectedEventsLeft = getAllExpectedEvents();
+
+        // check is all expected events were received
+        if (expectedEventsLeft.size() > 0) {
+            for (DebuggerEventData.DebugEventData eventData : expectedEventsLeft) {
+                if (!isMissedEventAllowed(eventData.eventClass)) {
+                    setSuccess(false);
+                    log.complain("Expected event was not generated: " + eventData);
+                }
+            }
+        }
+    }
+
+    private String eventToString(Event event) {
+        try {
+            if (event instanceof MonitorContendedEnterEvent)
+                return event + ". Details(MonitorContendedEnterEvent):" + " Monitor: " + ((MonitorContendedEnterEvent) event).monitor() + " Thread: "
+                        + ((MonitorContendedEnterEvent) event).thread();
+            else if (event instanceof MonitorContendedEnteredEvent)
+                return event + ". Details(MonitorContendedEnteredEvent):" + " Monitor: " + ((MonitorContendedEnteredEvent) event).monitor()
+                        + " Thread: " + ((MonitorContendedEnteredEvent) event).thread();
+            else if (event instanceof MonitorWaitEvent)
+                return event + ". Details(MonitorWaitEvent):" + " Monitor: " + ((MonitorWaitEvent) event).monitor() + " Thread: "
+                        + ((MonitorWaitEvent) event).thread() + " Timeout: " + ((MonitorWaitEvent) event).timeout();
+            else if (event instanceof MonitorWaitedEvent)
+                return event + ". Details(MonitorWaitedEvent):" + " Monitor: " + ((MonitorWaitedEvent) event).monitor() + " Thread: "
+                        + ((MonitorWaitedEvent) event).thread() + " Timedout: " + ((MonitorWaitedEvent) event).timedout();
+
+            return event.toString();
+        }
+        // this exception can occur when unexpected event was received
+        catch (ObjectCollectedException e) {
+            // allowExtraEvents=true extra events are not treated as error
+            if (!isExtraEventAllowed(event.getClass())) {
+                setSuccess(false);
+                e.printStackTrace(log.getOutStream());
+                log.complain("Unexpected ObjectCollectedException was caught, possible unexpected event was received");
+            }
+
+            return event.getClass().getName() + " [ Can't get full description, ObjectCollectedException was thrown ]";
+        }
+    }
+
+    // events received during test execution are stored here
+    private Map<Class<?>, List<Event>> allReceivedEvents = new HashMap<Class<?>, List<Event>>();
+
+    private List<Event> getAllReceivedEvents() {
+        List<Event> result = new LinkedList<Event>();
+
+        for (Class<?> eventClass : allReceivedEvents.keySet()) {
+            result.addAll(allReceivedEvents.get(eventClass));
+        }
+
+        return result;
+    }
+
+    protected Map<Class<?>, List<DebuggerEventData.DebugEventData>> allExpectedEvents = new HashMap<Class<?>, List<DebuggerEventData.DebugEventData>>();
+
+    private List<DebuggerEventData.DebugEventData> getAllExpectedEvents() {
+        List<DebuggerEventData.DebugEventData> result = new LinkedList<DebuggerEventData.DebugEventData>();
+
+        for (Class<?> eventClass : allExpectedEvents.keySet()) {
+            result.addAll(allExpectedEvents.get(eventClass));
+        }
+
+        return result;
+    }
+
+    // find in debuggee VM and add to the list 'allExpectedEvents' instances
+    // of classes representing generated events
+    protected void initExpectedEvents(TestedEventData testedEventData[]) {
+        List<DebuggerEventData.DebugEventData> events;
+
+        ReferenceType referenceType = debuggee.classByName(debuggeeClassNameWithoutArgs());
+
+        ArrayReference generatedEvents = (ArrayReference) referenceType.getValue(referenceType.fieldByName("generatedEvents"));
+
+        for (TestedEventData eventData : testedEventData) {
+            events = new LinkedList<DebuggerEventData.DebugEventData>();
+            allExpectedEvents.put(eventData.eventClass, events);
+        }
+
+        for (int i = 0; i < generatedEvents.length(); i++) {
+            ObjectReference debuggeeMirror = (ObjectReference) generatedEvents.getValue(i);
+
+            for (TestedEventData eventData : testedEventData) {
+
+                if (debuggeeMirror.referenceType().name().equals(eventData.eventDataMirrorClass.getName())) {
+                    events = allExpectedEvents.get(eventData.eventClass);
+
+                    /*
+                     * Use reflection to create object representing generated
+                     * event Event data class should has constructor with single
+                     * parameter of type com.sun.jdi.ObjectReference
+                     */
+                    Constructor<?> constructor;
+
+                    try {
+                        constructor = eventData.eventDataClass.getConstructor(new Class[] { ObjectReference.class });
+                    } catch (NoSuchMethodException e) {
+                        TestBug testBug = new TestBug(
+                                "Class representing debug event data should implement constructor with single parameter of type com.sun.jdi.ObjectReference");
+                        testBug.initCause(e);
+                        throw testBug;
+                    }
+
+                    DebuggerEventData.DebugEventData expectedEvent;
+
+                    try {
+                        expectedEvent = (DebuggerEventData.DebugEventData) constructor.newInstance(new Object[] { debuggeeMirror });
+                    } catch (Exception e) {
+                        TestBug testBug = new TestBug("Error when create debug event data: " + e);
+                        testBug.initCause(e);
+                        throw testBug;
+                    }
+                    events.add(expectedEvent);
+                }
+            }
+        }
+    }
+
+    private void printFiltersInfo() {
+        if (eventFilters.size() > 0) {
+            log.display("Use following filters: ");
+
+            for (EventFilters.DebugEventFilter filter : eventFilters)
+                log.display("" + filter);
+        } else {
+            log.display("Don't use event filters");
+        }
+    }
+
+    // filters used in test
+    protected List<EventFilters.DebugEventFilter> eventFilters = new LinkedList<EventFilters.DebugEventFilter>();
+
+    // Check is object generating events matches all filters,
+    // if object was accepted by all filters set this object's field
+    // 'saveEventData' to 'true', otherwise to 'false',
+    private void checkEventGenerator(ThreadReference eventThread, ObjectReference executor) {
+        boolean acceptedByFilters = true;
+
+        for (EventFilters.DebugEventFilter eventFilter : eventFilters) {
+            if (!eventFilter.isObjectMatch(executor, eventThread)) {
+                acceptedByFilters = false;
+                break;
+            }
+        }
+
+        try {
+            executor.setValue(executor.referenceType().fieldByName("saveEventData"), vm.mirrorOf(acceptedByFilters));
+        } catch (Exception e) {
+            throw new TestBug("Unexpected exception when change object field in debugee VM: " + e, e);
+        }
+    }
+
+    /*
+     * Find all event generating threads in debuggee VM (instances of
+     * nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread) all these
+     * threads have special field - 'executor', this is object which generates
+     * events. If event generating thread and event generating object was
+     * accepted by all filters generating object should store information about
+     * all generated events and this information will be available for debugger
+     */
+    protected void initializeEventGenerators() {
+        printFiltersInfo();
+
+        List<ThreadReference> eventThreads = getEventThreads();
+
+        for (ThreadReference eventThread : eventThreads) {
+            ObjectReference executor = (ObjectReference) eventThread.getValue(eventThread.referenceType().fieldByName("executor"));
+            checkEventGenerator(eventThread, executor);
+        }
+
+        // debuggee's main thread also can generate events, need to filter it in
+        // the same way as other threads
+        checkEventGenerator(debuggee.threadByName(JDIEventsDebuggee.MAIN_THREAD_NAME), findSingleObjectReference(debuggeeClassNameWithoutArgs()));
+    }
+
+    // find instances of nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread
+    protected List<ThreadReference> getEventThreads() {
+        ReferenceType referenceType = debuggee.classByName(JDIEventsDebuggee.EventActionsThread.class.getName());
+        List<ObjectReference> debuggeeEventThreads = referenceType.instances(0);
+
+        List<ThreadReference> result = new LinkedList<ThreadReference>();
+        for (ObjectReference threadReference : debuggeeEventThreads)
+            result.add((ThreadReference) threadReference);
+
+        return result;
+    }
+
+    // find instances of nsk.share.jdi.MonitorEventsDebuggee$MonitorActionsThread,
+    // and get value of this object's field with name 'executor'
+    protected List<ObjectReference> getEventObjects() {
+        List<ObjectReference> eventObjects = new LinkedList<ObjectReference>();
+
+        List<ThreadReference> eventThreads = getEventThreads();
+
+        for (ThreadReference eventThread : eventThreads) {
+            eventObjects.add((ObjectReference) eventThread.getValue(eventThread.referenceType().fieldByName("executor")));
+        }
+
+        return eventObjects;
+    }
+
+    // remove all filters, received and expected events
+    private void clearTestData() {
+        allExpectedEvents.clear();
+        allReceivedEvents.clear();
+        eventFilters.clear();
+        eventsNotGenerated = false;
+    }
+
+    private boolean isEventSupported(EventType eventType) {
+        switch (eventType) {
+        case MONITOR_CONTENTED_ENTER:
+        case MONITOR_CONTENTED_ENTERED:
+        case MONITOR_WAIT:
+        case MONITOR_WAITED:
+            return vm.canRequestMonitorEvents();
+
+        default:
+            throw new TestBug("Invalid tested event type: " + eventType);
+        }
+    }
+
+    // create instance of EventRequest depending on given eventType
+    private EventRequest createTestRequest(EventType eventType) {
+        switch (eventType) {
+        case MONITOR_CONTENTED_ENTER:
+            return debuggee.getEventRequestManager().createMonitorContendedEnterRequest();
+        case MONITOR_CONTENTED_ENTERED:
+            return debuggee.getEventRequestManager().createMonitorContendedEnteredRequest();
+        case MONITOR_WAIT:
+            return debuggee.getEventRequestManager().createMonitorWaitRequest();
+        case MONITOR_WAITED:
+            return debuggee.getEventRequestManager().createMonitorWaitedRequest();
+
+        default:
+            throw new TestBug("Invalid tested event type: " + eventType);
+        }
+    }
+
+    // create command depending on given eventType
+    private String createCommand(EventType eventTypes[], int eventsNumber) {
+        String command = JDIEventsDebuggee.COMMAND_CREATE_ACTIONS_EXECUTORS + ":" + eventsNumber + ":";
+
+        for (EventType eventType : eventTypes) {
+            switch (eventType) {
+            case MONITOR_CONTENTED_ENTER:
+            case MONITOR_CONTENTED_ENTERED:
+            case MONITOR_WAIT:
+            case MONITOR_WAITED:
+                command += " " + eventType.name();
+                break;
+
+            default:
+                throw new TestBug("Invalid tested event type: " + eventType);
+            }
+        }
+
+        return command;
+    }
+
+    // get list of event requests from EventRequestManager depending on the given eventType
+    private List<?> getEventRequestsFromManager(EventType eventType) {
+        switch (eventType) {
+        case MONITOR_CONTENTED_ENTER:
+            return debuggee.getEventRequestManager().monitorContendedEnterRequests();
+        case MONITOR_CONTENTED_ENTERED:
+            return debuggee.getEventRequestManager().monitorContendedEnteredRequests();
+        case MONITOR_WAIT:
+            return debuggee.getEventRequestManager().monitorWaitRequests();
+        case MONITOR_WAITED:
+            return debuggee.getEventRequestManager().monitorWaitedRequests();
+
+        default:
+            throw new TestBug("Invalid tested event type: " + eventType);
+        }
+    }
+
+    protected EventHandler eventHandler;
+
+    private EventListener eventListener;
+
+    // perform event generation before test begins to load all using classes
+    // and avoid unexpected events related to classloading
+    protected void prepareDebuggee(EventType[] eventTypes) {
+        initDefaultBreakpoint();
+
+        eventHandler = new EventHandler(debuggee, log);
+        eventHandler.startListening();
+
+        // use event listener which just skip all received events
+        DummyEventListener dummyEventListener = new DummyEventListener();
+        eventHandler.addListener(dummyEventListener);
+
+        EventRequest eventRequests[] = new EventRequest[eventTypes.length];
+
+        for (int i = 0; i < eventRequests.length; i++) {
+            eventRequests[i] = createTestRequest(eventTypes[i]);
+            eventRequests[i].setSuspendPolicy(EventRequest.SUSPEND_NONE);
+            eventRequests[i].enable();
+        }
+
+        // debuggee should create event generators
+        pipe.println(createCommand(eventTypes, 1));
+
+        if (!isDebuggeeReady())
+            return;
+
+        // start event generation
+        pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION);
+
+        if (!isDebuggeeReady())
+            return;
+
+        for (int i = 0; i < eventRequests.length; i++)
+            eventRequests[i].disable();
+
+        dummyEventListener.waitBreakpoint();
+
+        eventHandler.removeListener(dummyEventListener);
+
+        pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION);
+
+        if (!isDebuggeeReady())
+            return;
+
+        eventListener = new EventListener(eventDataByEventTypes(eventTypes));
+        eventHandler.addListener(eventListener);
+    }
+
+    /*
+     * Method for stress testing, allows specify requests for several event
+     * types, number of events which should be generated during test and number
+     * of threads which simultaneously generate events
+     */
+    protected void stressTestTemplate(EventType[] eventTypes, int eventsNumber, int threadsNumber) {
+        for (EventType eventType : eventTypes) {
+            if (!isEventSupported(eventType)) {
+                log.complain("Can't test event because of it isn't supported: " + eventType);
+                return;
+            }
+        }
+
+        // Used framework is intended for testing event filters and debuggee
+        // creates 3 threads performing event generation and there is possibility
+        // to filter events from some threads
+        for (int i = 0; i < threadsNumber; i++) {
+            pipe.println(createCommand(eventTypes, eventsNumber));
+
+            if (!isDebuggeeReady())
+                return;
+        }
+
+        // clear data(if this method is executed several times)
+        clearTestData();
+
+        initializeEventGenerators();
+
+        EventRequest eventRequests[] = new EventRequest[eventTypes.length];
+
+        // create event requests
+        for (int i = 0; i < eventTypes.length; i++) {
+            eventRequests[i] = createTestRequest(eventTypes[i]);
+            eventRequests[i].setSuspendPolicy(EventRequest.SUSPEND_NONE);
+            eventRequests[i].enable();
+
+            log.display("Use following event request: " + eventRequests[i]);
+        }
+
+        // stressTestTemplate can control only execution time, so ignore iteration count
+        stresser.start(0);
+        try {
+            // start event generation
+            pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION);
+
+            if (!isDebuggeeReady())
+                return;
+
+            // check is stressTime exceeded
+            while (stresser.continueExecution()) {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    unexpectedException(e);
+                }
+
+                // periodically check is test completed
+                if (eventListener.breakpointWasReceived)
+                    break;
+            }
+        } finally {
+            stresser.finish();
+        }
+
+        // debugger should interrupt test because of timeout
+        if (!eventListener.breakpointWasReceived) {
+
+            eventListener.executionWasInterrupted = true;
+
+            log.complain("WARNING: time is exceeded, interrupt test");
+
+            pipe.println(JDIEventsDebuggee.COMMAND_STOP_EXECUTION);
+
+            if (!isDebuggeeReady())
+                return;
+        }
+
+        pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION);
+
+        if (!isDebuggeeReady())
+            return;
+
+        for (int i = 0; i < eventRequests.length; i++)
+            eventRequests[i].disable();
+    }
+
+    /*
+     * Hook method for subclasses implementing tests against event filters (it is called from eventFilterTestTemplate)
+     */
+    protected EventFilters.DebugEventFilter[] createTestFilters(int testedFilterIndex) {
+        throw new TestBug("Not implemented");
+    }
+
+    /*
+     * Test event request with filter
+     *
+     * Also this method check following:
+     * - InvalidRequestStateException is thrown if add filter for deleted or enabled request
+     * - EventRequestManager.xxxRequests() returns created event request
+     */
+    protected void eventFilterTestTemplate(EventType eventType, int testedFilterIndex) {
+        if (!isEventSupported(eventType)) {
+            log.complain("Can't test event because of it isn't supported: " + eventType);
+            return;
+        }
+
+        // debuggee create event generators
+        pipe.println(createCommand(new EventType[] { eventType }, 1));
+
+        if (!isDebuggeeReady())
+            return;
+
+        clearTestData();
+
+        EventFilters.DebugEventFilter[] filters = createTestFilters(testedFilterIndex);
+
+        for (EventFilters.DebugEventFilter filter : filters) {
+            if (filter.isSupported(vm))
+                eventFilters.add(filter);
+            else {
+                log.complain("Can't test filter because of it isn't supported: " + filter);
+                return;
+            }
+        }
+
+        initializeEventGenerators();
+
+        // create event request
+        EventRequest request = createTestRequest(eventType);
+        request.setSuspendPolicy(EventRequest.SUSPEND_NONE);
+
+        // try add filter to enabled request, expect
+        // 'InvalidRequestStateException'
+        request.enable();
+        try {
+            for (EventFilters.DebugEventFilter filter : filters)
+                filter.addFilter(request);
+
+            setSuccess(false);
+            log.complain("Expected 'InvalidRequestStateException' was not thrown");
+        } catch (InvalidRequestStateException e) {
+            // expected exception
+        } catch (Throwable e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+        // add event filter
+        request.disable();
+
+        for (EventFilters.DebugEventFilter filter : filters)
+            addFilter(filter, request);
+
+        request.enable();
+
+        log.display("Use following event request: " + request);
+
+        // start event generation
+        pipe.println(JDIEventsDebuggee.COMMAND_START_EXECUTION);
+
+        if (!isDebuggeeReady())
+            return;
+
+        // wait execution completion
+        pipe.println(JDIEventsDebuggee.COMMAND_WAIT_EXECUTION_COMPLETION);
+
+        if (!isDebuggeeReady())
+            return;
+
+        // check that method EventRequestManager.xxxRequests() return created
+        // request
+        if (!getEventRequestsFromManager(eventType).contains(request)) {
+            setSuccess(false);
+            log.complain("EventRequestManager doesn't return request: " + request);
+        }
+
+        // delete event request
+        debuggee.getEventRequestManager().deleteEventRequest(request);
+
+        // try add filter to removed request, expect
+        // 'InvalidRequestStateException'
+        try {
+            for (EventFilters.DebugEventFilter filter : filters)
+                filter.addFilter(request);
+            setSuccess(false);
+            log.complain("Expected 'InvalidRequestStateException' was not thrown");
+        } catch (InvalidRequestStateException e) {
+            // expected exception
+        } catch (Throwable t) {
+            unexpectedException(t);
+        }
+    }
+
+    private void addFilter(EventFilters.DebugEventFilter filter, EventRequest request) {
+        try {
+            filter.addFilter(request);
+        } catch (Throwable t) {
+            unexpectedException(t);
+        }
+    }
+
+    // used to parse parameters -allowExtraEvents and -allowMissedEvents
+    private Class<?>[] createEventClassArray(String string) {
+        String eventTypesNames[] = string.split(":");
+        EventType eventTypes[] = new EventType[eventTypesNames.length];
+        try {
+            for (int i = 0; i < eventTypesNames.length; i++) {
+                eventTypes[i] = EventType.valueOf(eventTypesNames[i]);
+            }
+        } catch (IllegalArgumentException e) {
+            throw new TestBug("Invalid event type", e);
+        }
+
+        if (eventTypesNames.length == 0)
+            throw new TestBug("Event types weren't specified");
+
+        Class<?>[] result = new Class[eventTypesNames.length];
+
+        for (int i = 0; i < result.length; i++)
+            result[i] = testedEventData.get(eventTypes[i]).eventClass;
+
+        return result;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MockReferenceType.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A mock implementation of com.sun.jdi.ReferenceType interface.
+ */
+
+public class MockReferenceType implements ReferenceType {
+
+    private final String signature;
+    private final String name;
+    private final VirtualMachine virtualMachine;
+
+    private MockReferenceType(VirtualMachine virtualMachine, String signature, String name) {
+        this.signature = signature;
+        this.name = name;
+        this.virtualMachine = virtualMachine;
+    }
+
+    @Override
+    public String signature() {
+        return signature;
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public String genericSignature() {
+        return null;
+    }
+
+    @Override
+    public ClassLoaderReference classLoader() {
+        return null;
+    }
+
+    @Override
+    public String sourceName() throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<String> sourceNames(String stratum) throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<String> sourcePaths(String stratum) throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public String sourceDebugExtension() throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public boolean isStatic() {
+        return false;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return false;
+    }
+
+    @Override
+    public boolean isFinal() {
+        return false;
+    }
+
+    @Override
+    public boolean isPrepared() {
+        return false;
+    }
+
+    @Override
+    public boolean isVerified() {
+        return false;
+    }
+
+    @Override
+    public boolean isInitialized() {
+        return false;
+    }
+
+    @Override
+    public boolean failedToInitialize() {
+        return false;
+    }
+
+    @Override
+    public List<Field> fields() {
+        return null;
+    }
+
+    @Override
+    public List<Field> visibleFields() {
+        return null;
+    }
+
+    @Override
+    public List<Field> allFields() {
+        return null;
+    }
+
+    @Override
+    public Field fieldByName(String fieldName) {
+        return null;
+    }
+
+    @Override
+    public List<Method> methods() {
+        return null;
+    }
+
+    @Override
+    public List<Method> visibleMethods() {
+        return null;
+    }
+
+    @Override
+    public List<Method> allMethods() {
+        return null;
+    }
+
+    @Override
+    public List<Method> methodsByName(String name) {
+        return null;
+    }
+
+    @Override
+    public List<Method> methodsByName(String name, String signature) {
+        return null;
+    }
+
+    @Override
+    public List<ReferenceType> nestedTypes() {
+        return null;
+    }
+
+    @Override
+    public Value getValue(Field field) {
+        return null;
+    }
+
+    @Override
+    public Map<Field, Value> getValues(List<? extends Field> fields) {
+        return null;
+    }
+
+    @Override
+    public ClassObjectReference classObject() {
+        return null;
+    }
+
+    @Override
+    public List<Location> allLineLocations() throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<Location> allLineLocations(String stratum, String sourceName) throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<Location> locationsOfLine(int lineNumber) throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<Location> locationsOfLine(String stratum, String sourceName, int lineNumber)
+            throws AbsentInformationException {
+        return null;
+    }
+
+    @Override
+    public List<String> availableStrata() {
+        return null;
+    }
+
+    @Override
+    public String defaultStratum() {
+        return null;
+    }
+
+    @Override
+    public List<ObjectReference> instances(long maxInstances) {
+        return null;
+    }
+
+    @Override
+    public int majorVersion() {
+        return 0;
+    }
+
+    @Override
+    public int minorVersion() {
+        return 0;
+    }
+
+    @Override
+    public int constantPoolCount() {
+        return 0;
+    }
+
+    @Override
+    public byte[] constantPool() {
+        return new byte[0];
+    }
+
+    @Override
+    public VirtualMachine virtualMachine() {
+        return virtualMachine;
+    }
+
+    @Override
+    public int modifiers() {
+        return 0;
+    }
+
+    @Override
+    public boolean isPrivate() {
+        return false;
+    }
+
+    @Override
+    public boolean isPackagePrivate() {
+        return false;
+    }
+
+    @Override
+    public boolean isProtected() {
+        return false;
+    }
+
+    @Override
+    public boolean isPublic() {
+        return false;
+    }
+
+    @Override
+    public int compareTo(ReferenceType o) {
+        return 0;
+    }
+
+    /*
+     * Creates a mock instance of com.sun.tools.jdi.ObjectReference with a given type.
+     */
+
+    public static Value createObjectReference(VirtualMachine virtualMachine, String typeSignature, String typeName)
+            throws Exception {
+
+        Class clazz = Class.forName("com.sun.tools.jdi.ObjectReferenceImpl");
+        java.lang.reflect.Constructor c = clazz.getDeclaredConstructor(VirtualMachine.class, long.class);
+        c.setAccessible(true);
+        Value objRef = (Value) c.newInstance(virtualMachine, 0);
+
+        Type mockType = new MockReferenceType(virtualMachine, typeSignature, typeName);
+        java.lang.reflect.Field typeField = clazz.getDeclaredField("type");
+        typeField.setAccessible(true);
+        typeField.set(objRef, mockType);
+
+        return objRef;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MonitorEnterExecutor.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "jni.h"
+#include "nsk_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_PTR
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG_2(x, y) y
+#define JNI_ENV_ARG_3(x,y, z) y, z
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG_2(x,y) x, y
+#define JNI_ENV_ARG_3(x,y, z) x, y, z
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+JNIEXPORT void JNICALL
+Java_nsk_share_jdi_MonitorEnterExecutor_nativeJNIMonitorEnter(JNIEnv *env, jobject thisObject)
+{
+        jint success;
+
+        success  = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero"));
+        }
+
+        success  = JNI_ENV_PTR(env)->MonitorExit(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorExit return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorExit return non-zero"));
+        }
+}
+
+JNIEXPORT void JNICALL
+Java_nsk_share_jdi_MonitorEnterExecutor_11Subclass_nativeJNIMonitorEnter(JNIEnv *env, jobject thisObject)
+{
+        jint success;
+
+        success  = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero"));
+        }
+
+        success  = JNI_ENV_PTR(env)->MonitorExit(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorExit return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorExit return non-zero"));
+        }
+}
+
+JNIEXPORT void JNICALL
+Java_nsk_share_jdi_MonitorEnterExecutor_12Subclass_nativeJNIMonitorEnter(JNIEnv *env, jobject thisObject)
+{
+        jint success;
+
+        success  = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero"));
+        }
+
+        success  = JNI_ENV_PTR(env)->MonitorExit(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorExit return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorExit return non-zero"));
+        }
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/MonitorEventsDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.util.*;
+import nsk.share.TestBug;
+import nsk.share.locks.MonitorLockingThread;
+
+/*
+ * This class generates MonitorWaitEvent and MonitorWaitedEvent
+ */
+class MonitorWaitExecutor extends EventActionsExecutor {
+    // MonitorWaited event may occurs when waiting thread was interrupted,
+    // notified by notify or notifyAll, or when timeout expired
+    enum ExitFromWaitType {
+        EXIT_WITH_TIMEOUT,
+        INTERRUPT,
+        NOTIFY,
+        NOTIFY_ALL
+    }
+
+    // this thread forces MonitorWaitExecutor to exit from wait()
+    class AuxiliaryThread extends Thread {
+        private Thread threadToInterrupt;
+
+        private Object monitor;
+
+        public AuxiliaryThread(Thread threadToInterrupt, Object monitor) {
+            this.threadToInterrupt = threadToInterrupt;
+            this.monitor = monitor;
+        }
+
+        public void run() {
+            // wait when interrupted thread switches state to 'TIMED_WAITING'
+            while ((threadToInterrupt.getState() != Thread.State.WAITING) && !exitedFromWait) {
+                yield();
+            }
+
+            // threadToInterrupt 'spuriously' exited from wait()
+            if(exitedFromWait)
+                return;
+
+            if (exitFromWaitType == ExitFromWaitType.INTERRUPT) {
+                threadToInterrupt.interrupt();
+            } else if ((exitFromWaitType == ExitFromWaitType.NOTIFY)
+                    || (exitFromWaitType == ExitFromWaitType.NOTIFY_ALL)) {
+                /*
+                 * NOTE: thread's state WAITING doesn't guarantee that thread released
+                 * monitor, and entering to the next synchronized block may cause MonitorContentedEnterEvent
+                 * (if corresponding request was created).
+                 *
+                 * Debugger should take in account this issue.
+                 */
+                synchronized (monitor) {
+                    if (exitFromWaitType == ExitFromWaitType.NOTIFY)
+                        monitor.notify();
+                    else if (exitFromWaitType == ExitFromWaitType.NOTIFY_ALL)
+                        monitor.notifyAll();
+                }
+            }
+        }
+    }
+
+    // thread may 'spuriously' exit from wait(), in this case AuxiliaryThread shouldn't wait 'WAITING' state
+    private volatile boolean exitedFromWait;
+
+    // save data about MonitorWait events
+    private boolean monitorWait;
+
+    // save data about MonitorWaited events
+    private boolean monitorWaited;
+
+    public MonitorWaitExecutor(boolean monitorWait, boolean monitorWaited) {
+        this.monitorWait = monitorWait;
+        this.monitorWaited = monitorWaited;
+    }
+
+    protected ExitFromWaitType exitFromWaitType;
+
+    public void doEventAction() {
+        for (ExitFromWaitType exitType : ExitFromWaitType.values()) {
+            exitFromWaitType = exitType;
+
+            monitorWait();
+        }
+    }
+
+    protected void monitorWait() {
+
+        exitedFromWait = false;
+
+        long timeout;
+
+        if (exitFromWaitType == ExitFromWaitType.EXIT_WITH_TIMEOUT)
+            timeout = 100;
+        else
+            timeout = 0;
+
+        if (monitorWait) {
+            DebuggeeEventData.DebugMonitorWaitEventData eventData = new DebuggeeEventData.DebugMonitorWaitEventData(
+                    this, Thread.currentThread(), timeout, this);
+            addEventData(eventData);
+        }
+
+        if (monitorWaited) {
+            DebuggeeEventData.DebugMonitorWaitedEventData eventData = new DebuggeeEventData.DebugMonitorWaitedEventData(
+                    this, Thread.currentThread(),
+                    (exitFromWaitType == ExitFromWaitType.EXIT_WITH_TIMEOUT),
+                    this);
+            addEventData(eventData);
+        }
+
+        AuxiliaryThread auxiliaryThread = null;
+
+        if (exitFromWaitType != ExitFromWaitType.EXIT_WITH_TIMEOUT) {
+            auxiliaryThread = new AuxiliaryThread(Thread.currentThread(), this);
+            auxiliaryThread.start();
+        }
+
+        try {
+            eventMethod(timeout);
+        } catch (InterruptedException e) {
+            // expected exception
+        }
+
+        exitedFromWait = true;
+
+        if (auxiliaryThread != null) {
+            // don't using join, because of join is realized with using of
+            // wait(), and this method can generate unexpected events
+            while (auxiliaryThread.getState() != Thread.State.TERMINATED)
+                Thread.yield();
+        }
+    }
+
+    // move event actions to the separate method to simplify method redifinition
+    // in subclasses
+    synchronized protected void eventMethod(long timeout)
+            throws InterruptedException {
+        wait(timeout);
+    }
+
+}
+
+/*
+ * Subclass of MonitorWaitExecutor, define its own event method(copy of parent
+ * method), intended for event filters test
+ */
+class MonitorWaitExecutor_1Subclass extends MonitorWaitExecutor {
+    public MonitorWaitExecutor_1Subclass(boolean monitorWait,
+            boolean monitorWaited) {
+        super(monitorWait, monitorWaited);
+    }
+
+    synchronized protected void eventMethod(long timeout)
+            throws InterruptedException {
+        wait(timeout);
+    }
+}
+
+/*
+ * Subclass of MonitorWaitExecutor, define its own event method(copy of parent
+ * method), intended for event filters test
+ */
+class MonitorWaitExecutor_2Subclass extends MonitorWaitExecutor_1Subclass {
+    public MonitorWaitExecutor_2Subclass(boolean monitorWait,
+            boolean monitorWaited) {
+        super(monitorWait, monitorWaited);
+    }
+
+    synchronized protected void eventMethod(long timeout)
+            throws InterruptedException {
+        wait(timeout);
+    }
+}
+
+/*
+ * This class generates MonitorContendedEnterEvent and
+ * MonitorContendedEnteredEvent
+ */
+class MonitorEnterExecutor extends EventActionsExecutor {
+    /*
+     * Types of monitor acquiring:
+     * - through synchronized block
+     * - through synchronized method
+     * - through JNI MonitorEnter
+     */
+    static enum MonitorAcquireType {
+        SYNCHRONIZED_BLOCK,
+        SYNCHRONIZED_METHOD,
+        JNI_MONITOR_ENTER
+    }
+
+    // native method uses this class
+    private static final Class<?> jniError = nsk.share.TestJNIError.class;
+
+
+    static final String nativeLibararyName = "MonitorEnterExecutor";
+
+    static {
+        System.loadLibrary(nativeLibararyName);
+    }
+
+    // this thread forces MonitorLockingThread to release holding lock
+    static class LockFreeThread extends Thread {
+        private Thread blockedThread;
+
+        private MonitorLockingThread lockingThread;
+
+        public LockFreeThread(Thread blockedThread,
+                MonitorLockingThread lockingThread) {
+            this.blockedThread = blockedThread;
+            this.lockingThread = lockingThread;
+        }
+
+        public void run() {
+            // wait when blocked thread switches state to 'BLOCKED'
+            while (blockedThread.getState() != Thread.State.BLOCKED)
+                yield();
+
+            lockingThread.releaseLock();
+        }
+    }
+
+    private boolean monitorEnter;
+
+    private boolean monitorEntered;
+
+    public MonitorEnterExecutor(boolean monitorEnter, boolean monitorEntered) {
+        this.monitorEnter = monitorEnter;
+        this.monitorEntered = monitorEntered;
+    }
+
+    protected void monitorEnter() {
+        // locking thread acquires 'this' lock
+        MonitorLockingThread lockingThread = new MonitorLockingThread(this);
+        lockingThread.acquireLock();
+
+        if (monitorEnter) {
+            DebuggeeEventData.DebugMonitorEnterEventData eventData = new DebuggeeEventData.DebugMonitorEnterEventData(
+                    this, Thread.currentThread(), this);
+            addEventData(eventData);
+        }
+        if (monitorEntered) {
+            DebuggeeEventData.DebugMonitorEnteredEventData eventData = new DebuggeeEventData.DebugMonitorEnteredEventData(
+                    this, Thread.currentThread(), this);
+            addEventData(eventData);
+        }
+
+        /*
+         * This thread forces lockingThread to free 'this' lock when current thread's state will change to 'BLOCKED'
+         *
+         * NOTE: this method to provoke MonitorContended events isn't 100% robust
+         * Tests should take in account this issue.
+         *
+         */
+        LockFreeThread lockFreeThread = new LockFreeThread(Thread.currentThread(), lockingThread);
+        lockFreeThread.start();
+
+        // try to acquire 'this' lock
+        eventMethod();
+
+        while(lockingThread.getState() != Thread.State.TERMINATED)
+            Thread.yield();
+
+        while(lockFreeThread.getState() != Thread.State.TERMINATED)
+            Thread.yield();
+    }
+
+    private MonitorAcquireType monitorAcquireType;
+
+    // generate events in different ways
+    public void doEventAction() {
+        for (MonitorAcquireType monitorAcquireType : MonitorAcquireType.values()) {
+            this.monitorAcquireType = monitorAcquireType;
+            monitorEnter();
+        }
+    }
+
+    protected void eventMethod() {
+        switch (monitorAcquireType) {
+        case SYNCHRONIZED_BLOCK:
+            synchronizedBlock();
+            break;
+        case SYNCHRONIZED_METHOD:
+            synchronizedMethod();
+            break;
+        case JNI_MONITOR_ENTER:
+            nativeJNIMonitorEnter();
+            break;
+
+        default:
+            throw new TestBug("Invalid monitorAcquireType: "
+                    + monitorAcquireType);
+        }
+    }
+
+    // move event actions to the separate methods to simplify method
+    // redifinition in subclasses:
+
+    protected void synchronizedBlock() {
+        // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+        synchronized (this) {
+            // don't expect events for following synchronized block
+            synchronized (this) {
+            }
+        }
+    }
+
+    // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+    synchronized protected void synchronizedMethod() {
+        // don't expect events for following synchronized block
+        synchronized (this) {
+        }
+    }
+
+    // call JNI methods MonitorEnter and MonitorExit for 'this' object
+    protected native void nativeJNIMonitorEnter();
+
+}
+
+/*
+ * Subclass of MonitorEnterExecutor, defines its own event methods(copy of parent
+ * method), intended for event filters test
+ */
+class MonitorEnterExecutor_1Subclass extends MonitorEnterExecutor {
+    static {
+        System.loadLibrary(nativeLibararyName);
+    }
+
+    public MonitorEnterExecutor_1Subclass(boolean monitorEnter,
+            boolean monitorEntered) {
+        super(monitorEnter, monitorEntered);
+    }
+
+    protected void synchronizedBlock() {
+        // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+        synchronized (this) {
+        }
+    }
+
+    // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+    synchronized protected void synchronizedMethod() {
+    }
+
+    // call JNI methods MonitorEnter and MonitorExit for 'this' object
+    protected native void nativeJNIMonitorEnter();
+}
+
+/*
+ * Subclass of MonitorEnterExecutor, defines its own event methods(copy of parent
+ * method), intended for event filters test
+ */
+class MonitorEnterExecutor_2Subclass extends MonitorEnterExecutor_1Subclass {
+    static {
+        System.loadLibrary(nativeLibararyName);
+    }
+
+    public MonitorEnterExecutor_2Subclass(boolean monitorEnter,
+            boolean monitorEntered) {
+        super(monitorEnter, monitorEntered);
+    }
+
+    protected void synchronizedBlock() {
+        // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+        synchronized (this) {
+        }
+    }
+
+    // MonitorContendedEnterEvent and MonitorContendedEnteredEvent should occur here
+    synchronized protected void synchronizedMethod() {
+    }
+
+    // call JNI methods MonitorEnter and MonitorExit for 'this' object
+    protected native void nativeJNIMonitorEnter();
+}
+
+/*
+ * Class is used as base debuggee in tests for following events and event requests:
+ * - MonitorContendedEnterRequest / MonitorContendedEnterEvent
+ * - MonitorContendedEnteredRequest / MonitorContendedEnteredEvent
+ * - MonitorWaitRequest / MonitorWaitEvent
+ * - MonitorWaitedRequest / MonitorWaitedEvent
+ */
+public class MonitorEventsDebuggee extends JDIEventsDebuggee {
+    public static void main(String[] args) {
+        MonitorEventsDebuggee debuggee = new MonitorEventsDebuggee();
+        debuggee.doTest(args);
+    }
+
+    protected void createActionsExecutors(String description, int eventsCount) {
+        boolean monitorEnter = description
+                .contains(JDIEventsDebugger.EventType.MONITOR_CONTENTED_ENTER
+                        .name());
+        boolean monitorEntered = description
+                .contains(JDIEventsDebugger.EventType.MONITOR_CONTENTED_ENTERED
+                        .name());
+        boolean monitorWait = description
+                .contains(JDIEventsDebugger.EventType.MONITOR_WAIT.name());
+        boolean monitorWaited = description
+                .contains(JDIEventsDebugger.EventType.MONITOR_WAITED.name());
+
+        if (monitorEnter || monitorEntered || monitorWait || monitorWaited) {
+            createActionsExecutors(monitorEnter, monitorEntered, monitorWait,
+                    monitorWaited, eventsCount);
+        } else
+            throw new TestBug(
+                    "Invalid command format (required event not specified)");
+    }
+
+    private List<DebuggeeEventData.DebugMonitorEventData> eventsData = new ArrayList<DebuggeeEventData.DebugMonitorEventData>();
+
+    protected void clearResults() {
+        super.clearResults();
+        eventsData.clear();
+    }
+
+    private void createActionsExecutors(boolean monitorEnter,
+            boolean monitorEntered, boolean monitorWait, boolean monitorWaited,
+            int actionsCount) {
+        EventActionsThread thread;
+
+        // create 3 instances of generating objects of 3 different classes (for
+        // event filters tests)
+        if (monitorEnter || monitorEntered) {
+            thread = new EventActionsThread(new MonitorEnterExecutor(
+                    monitorEnter, monitorEntered), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+
+            thread = new EventActionsThread(new MonitorEnterExecutor_1Subclass(
+                    monitorEnter, monitorEntered), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+
+            thread = new EventActionsThread(new MonitorEnterExecutor_2Subclass(
+                    monitorEnter, monitorEntered), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+        }
+
+        // create 3 instances of generating objects of 3 different classes (for
+        // event filters tests)
+        if (monitorWait || monitorWaited) {
+            thread = new EventActionsThread(new MonitorWaitExecutor(
+                    monitorWait, monitorWaited), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+
+            thread = new EventActionsThread(new MonitorWaitExecutor_1Subclass(
+                    monitorWait, monitorWaited), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+
+            thread = new EventActionsThread(new MonitorWaitExecutor_2Subclass(
+                    monitorWait, monitorWaited), actionsCount);
+            thread.start();
+            eventActionsExecutorsPool.add(thread);
+        }
+    }
+
+    // start event generating threads and wait when all this threads finish
+    // execution
+    // override parent method because of Thread.join() used in parent method
+    // generates unexpected MonitorWait/MonitorWaited events
+    protected void startExecution() {
+        if (eventActionsExecutorsPool.size() == 0) {
+            throw new TestBug("ActionsExecutors were not created");
+        }
+
+        for (EventActionsThread thread : eventActionsExecutorsPool) {
+            thread.startExecution();
+        }
+
+        // wait completion of test threads in separate thread to free thread listening commands
+        executionControllingThread = new Thread(
+                new Runnable() {
+                    public void run() {
+                        boolean executionCompleted;
+                        do {
+                            try {
+                                // give time to event generators
+                                Thread.sleep(500);
+                            } catch (InterruptedException e) {
+                                unexpectedException(e);
+                            }
+                            executionCompleted = true;
+                            for (EventActionsThread thread : eventActionsExecutorsPool) {
+                                if (thread.isAlive()) {
+                                    executionCompleted = false;
+                                    break;
+                                }
+                            }
+                        } while (!executionCompleted);
+
+                        completeExecution();
+                    }
+                });
+
+        executionControllingThread.start();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/OwnedMonitorsDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.locks.LockingThread;
+import nsk.share.TestBug;
+
+/*
+ *  Class is used as base debuggee in tests for ThreadReference.ownedMonitorsAndFrames().
+ *
+ *  Class handle commands for creating threads which acquires and relinquish locks in different ways,
+ *  nsk.share.locks.LockingThread is used for this purposes.
+ *
+ *  Information about acquired monitors can be stored in static array 'monitorsInfo' and in this way this
+ *  data is available for debugger.
+ */
+public class OwnedMonitorsDebuggee extends AbstractJDIDebuggee {
+    // command:threadName:stackFrameDescription
+    public static final String COMMAND_CREATE_LOCKING_THREAD = "createLockingThread";
+
+    // command:threadName
+    public static final String COMMAND_STOP_LOCKING_THREAD = "stopLockingThread";
+
+    // command:threadName
+    public static final String COMMAND_UPDATE_MONITOR_INFO = "updateMonitorInfo";
+
+    // command:threadName
+    public static final String COMMAND_EXIT_SINGLE_FRAME = "exitSingleFrame";
+
+    // command:threadName:monitorIndex
+    public static final String COMMAND_RELINQUISH_MONITOR = "relinquishMonitor";
+
+    // command:threadName
+    public static final String COMMAND_ACQUIRE_RELINQUISHED_MONITOR = "acquireRelinquishedMonitor";
+
+    // from this array information about acquired monitors is available for debugger
+    // (this class is used in stress tests where several tests are executed consecutively, but in this case using of
+    // static array shouldn't cause problems because of before using of array 'monitorsInfo' debugger
+    // uses COMMAND_UPDATE_MONITOR_INFO which updates this array with latest data, so excution of one test shouldn't
+    // affect other tests)
+    public static LockingThread.DebugMonitorInfo monitorsInfo[];
+
+    private boolean returnJNIMonitors;
+
+    public final static String mainThreadName = "OwnedMonitorDebuggeeMainThread";
+
+    protected String[] doInit(String[] args) {
+        Thread.currentThread().setName(mainThreadName);
+
+        args = super.doInit(args);
+
+        ArrayList<String> standardArgs = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equalsIgnoreCase("-returnJNIMonitors")) {
+                returnJNIMonitors = true;
+            } else
+                standardArgs.add(args[i]);
+        }
+
+        return standardArgs.toArray(new String[] {});
+    }
+
+    public boolean parseCommand(String command) {
+        if (super.parseCommand(command))
+            return true;
+
+        StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command));
+        tokenizer.whitespaceChars(':', ':');
+        tokenizer.wordChars('_', '_');
+
+        try {
+            if (command.startsWith(COMMAND_ACQUIRE_RELINQUISHED_MONITOR)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                acquireRelinquishMonitor(threadName);
+
+                return true;
+            } else if (command.startsWith(COMMAND_RELINQUISH_MONITOR)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_NUMBER)
+                    throw new TestBug("Invalid command format: " + command);
+
+                int monitorIndex = (int) tokenizer.nval;
+
+                relinquishMonitor(threadName, monitorIndex);
+
+                return true;
+            } else if (command.startsWith(COMMAND_CREATE_LOCKING_THREAD)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                List<String> stackFramesDescription = new ArrayList<String>();
+
+                while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
+                    stackFramesDescription.add(tokenizer.sval);
+                }
+
+                createLockingThread(threadName, stackFramesDescription);
+                return true;
+            } else if (command.startsWith(COMMAND_STOP_LOCKING_THREAD)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                stopLockingThread(threadName);
+
+                return true;
+            } else if (command.startsWith(COMMAND_UPDATE_MONITOR_INFO)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                updateMonitorInfo(threadName);
+
+                return true;
+            } else if (command.startsWith(COMMAND_EXIT_SINGLE_FRAME)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String threadName = tokenizer.sval;
+
+                exitSingleFrame(threadName);
+
+                return true;
+            }
+        } catch (IOException e) {
+            throw new TestBug("Invalid command format: " + command);
+        }
+
+        return false;
+    }
+
+    public void acquireRelinquishMonitor(String threadName) {
+        LockingThread thread = getThread(threadName);
+        thread.acquireRelinquishedMonitor();
+
+        thread.waitState();
+        updateMonitorInfo(threadName);
+    }
+
+    public void relinquishMonitor(String threadName, int monitorIndex) {
+        LockingThread thread = getThread(threadName);
+        thread.relinquishMonitor(monitorIndex);
+
+        thread.waitState();
+        updateMonitorInfo(threadName);
+    }
+
+    private void updateMonitorInfo(String threadName) {
+        LockingThread thread = getThread(threadName);
+        monitorsInfo = thread.getMonitorsInfo(returnJNIMonitors);
+    }
+
+    private Map<String, LockingThread> threads = new TreeMap<String, LockingThread>();
+
+    private LockingThread getThread(String threadName) {
+        LockingThread thread = threads.get(threadName);
+
+        if (thread == null)
+            throw new TestBug("Locking thread with name: " + threadName + " was not created");
+
+        return thread;
+    }
+
+    private void stopLockingThread(String threadName) {
+        LockingThread thread = getThread(threadName);
+        thread.stopLockingThread();
+        thread.waitState();
+
+        updateMonitorInfo(threadName);
+    }
+
+    private void exitSingleFrame(String threadName) {
+        LockingThread thread = getThread(threadName);
+        thread.exitSingleFrame();
+        thread.waitState();
+
+        updateMonitorInfo(threadName);
+    }
+
+    private void createLockingThread(String threadName, List<String> stackFramesDescription) {
+        if (threads.get(threadName) != null)
+            throw new TestBug("Locking thread with name: " + threadName + " already exists");
+
+        LockingThread thread = new LockingThread(log, stackFramesDescription);
+        thread.setName(threadName);
+        thread.start();
+        thread.waitState();
+
+        threads.put(threadName, thread);
+
+        updateMonitorInfo(threadName);
+    }
+
+    public static void main(String args[]) {
+        OwnedMonitorsDebuggee debuggee = new OwnedMonitorsDebuggee();
+        debuggee.doTest(args);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/OwnedMonitorsDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+import com.sun.jdi.*;
+
+import nsk.share.Consts;
+
+/*
+ *  Class is used as base debugger in tests for ThreadReference.ownedMonitorsAndFrames().
+ *
+ *  In all this test similar scenario is used:
+ *      - debugger VM force debugge VM to create test thread which acquires different monitors
+ *      - when test thread acquire all monitors debuggee save information about all acquired monitors in special array 'monitorsInfo'
+ *      - debugger read data from 'monitorsInfo' and compare it with data returned by ThreadReference.ownedMonitorsAndFrames()
+ */
+public class OwnedMonitorsDebugger extends TestDebuggerType2 {
+
+    /*
+     * debug data about monitor acquired by debuggee test thread,
+     * intended to compare with data returned by ThreadReference.ownedMonitorsAndFrames
+     */
+    public static class DebugMonitorInfo {
+        // create DebugMonitorInfo using mirror of instance of nsk.share.locks.LockingThread.DebugMonitorInfo
+        DebugMonitorInfo(ObjectReference debuggeeMirror) {
+            monitor = (ObjectReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("monitor"));
+            stackDepth = ((IntegerValue) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("stackDepth"))).intValue();
+            thread = (ThreadReference) debuggeeMirror.getValue(debuggeeMirror.referenceType().fieldByName("thread"));
+        }
+
+        public DebugMonitorInfo(ObjectReference monitor, int stackDepth, ThreadReference thread) {
+            this.monitor = monitor;
+            this.stackDepth = stackDepth;
+            this.thread = thread;
+        }
+
+        public ObjectReference monitor;
+
+        public int stackDepth;
+
+        public ThreadReference thread;
+    }
+
+    public static void main(String argv[]) {
+        System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+    }
+
+    public static int run(String argv[], PrintStream out) {
+        return new OwnedMonitorsDebugger().runIt(argv, out);
+    }
+
+    protected boolean canRunTest() {
+        if (!vm.canGetMonitorFrameInfo()) {
+            log.display("TEST CANCELED due to: vm.canGetMonitorFrameInfo() = false");
+            return false;
+        } else
+            return super.canRunTest();
+    }
+
+    protected String debuggeeClassName() {
+        return OwnedMonitorsDebuggee.class.getName();
+    }
+
+    // read debuggee's array 'monitorsInfo' containing information about acquired monitors
+    protected List<DebugMonitorInfo> getDebugMonitorsInfo() {
+        List<DebugMonitorInfo> result = new ArrayList<DebugMonitorInfo>();
+
+        ReferenceType referenceType = debuggee.classByName(debuggeeClassNameWithoutArgs());
+        ArrayReference monitorsInfo = (ArrayReference) referenceType.getValue(referenceType.fieldByName("monitorsInfo"));
+
+        for (int i = 0; i < monitorsInfo.length(); i++)
+            result.add(new DebugMonitorInfo((ObjectReference) monitorsInfo.getValue(i)));
+
+        return result;
+    }
+
+    private boolean compare(MonitorInfo actual, DebugMonitorInfo expected) {
+        boolean success = true;
+
+        if (actual.stackDepth() != expected.stackDepth) {
+            setSuccess(false);
+            success = false;
+            log.complain("Expected and actual monitor(" + actual.monitor() + ") stack depth differs, expected: " + expected.stackDepth + " actual: "
+                    + actual.stackDepth());
+        }
+
+        if (!actual.thread().equals(expected.thread)) {
+            setSuccess(false);
+            success = false;
+            log.complain("Expected and actual monitor(" + actual.monitor() + " thread differs, expected: " + expected.thread + " actual: "
+                    + actual.thread());
+        }
+
+        return success;
+    }
+
+    protected void compare(List<MonitorInfo> actualData, List<DebugMonitorInfo> expectedData) {
+        boolean success = true;
+
+        // compare total amount of monitors
+        if (actualData.size() != expectedData.size()) {
+            setSuccess(false);
+            success = false;
+            log.complain("Number of expected monitors and actual ones differs");
+            log.complain("Expected: " + expectedData.size() + ", actual: " + actualData.size());
+        }
+
+        // check that all expected monitors are contained in 'actualData'
+        for (DebugMonitorInfo expectedMonitorInfo : expectedData) {
+            boolean isMonitorFound = false;
+
+            for (MonitorInfo actualMonitorInfo : actualData) {
+                if (expectedMonitorInfo.monitor.equals(actualMonitorInfo.monitor())) {
+                    isMonitorFound = true;
+
+                    if (!compare(actualMonitorInfo, expectedMonitorInfo))
+                        success = false;
+
+                    break;
+                }
+            }
+
+            if (!isMonitorFound) {
+                setSuccess(false);
+                success = false;
+                log.complain("Expected monitor not found in result of ownedMonitorsAndFrames(): " + expectedMonitorInfo.monitor);
+            }
+        }
+
+        // check that all monitors from 'actualData' are contained in
+        // 'expectedData'
+        for (MonitorInfo actualMonitorInfo : actualData) {
+            boolean isMonitorFound = false;
+
+            for (DebugMonitorInfo expectedMonitorInfo : expectedData) {
+                if (actualMonitorInfo.monitor().equals(expectedMonitorInfo.monitor)) {
+                    isMonitorFound = true;
+                    break;
+                }
+            }
+
+            if (!isMonitorFound) {
+                setSuccess(false);
+                success = false;
+                log.complain("Unexpected monitor in result of ownedMonitorsAndFrames(): " + actualMonitorInfo.monitor() + " Depth: "
+                        + actualMonitorInfo.stackDepth() + " Thread: " + actualMonitorInfo.thread());
+            }
+        }
+
+        if (!success)
+            logDebugInfo(actualData, expectedData);
+    }
+
+    private void logDebugInfo(List<MonitorInfo> actualData, List<DebugMonitorInfo> expectedData) {
+        log.display("ACTUAL MONITORS (total " + actualData.size() + "):");
+
+        ThreadReference thread = null;
+
+        for (MonitorInfo monitorInfo : actualData) {
+            log.display("Monitor: " + monitorInfo.monitor());
+            log.display("Depth: " + monitorInfo.stackDepth());
+            log.display("Thread: " + monitorInfo.thread());
+            if (thread == null)
+                thread =  monitorInfo.thread();
+        }
+
+        log.display("EXPECTED MONITORS (total " + expectedData.size() + "):");
+
+        for (DebugMonitorInfo monitorInfo : expectedData) {
+            log.display("Monitor: " + monitorInfo.monitor);
+            log.display("Depth: " + monitorInfo.stackDepth);
+            log.display("Thread: " + monitorInfo.thread);
+            if (thread == null)
+                thread =  monitorInfo.thread;
+        }
+
+        if (thread != null) {
+            try {
+                log.display("Thread frames:");
+                for (StackFrame frame : thread.frames()) {
+                    Location location = frame.location();
+                    log.display(location.declaringType().name() + "." + location.method().name() + ", line: " + location.lineNumber());
+                }
+            } catch (Exception e) {
+                unexpectedException(e);
+            }
+        }
+    }
+
+    /*
+     * Check that ThreadReference.ownedMonitorsAndFrames() returns correct
+     * data before calling this method debuggee should save information about
+     * acquired monitors in special array 'monitorsInfo',
+     * debugger forces debuggee to do it using command 'COMMAND_UPDATE_MONITOR_INFO'
+     */
+    protected void checkMonitorInfo(ThreadReference threadReference) {
+        List<MonitorInfo> actualData = null;
+
+        try {
+            actualData = threadReference.ownedMonitorsAndFrames();
+        } catch (Exception e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+        List<DebugMonitorInfo> expectedData = getDebugMonitorsInfo();
+
+        compare(actualData, expectedData);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/PlugConnectors.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A Super class for pluggable connectors used by
+ * nsk/jdi/PlugConnectors tests
+ */
+
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+import com.sun.jdi.connect.*;
+import java.io.*;
+import java.util.*;
+
+public class PlugConnectors implements Connector {
+
+    String plugConnectorName = "Undefined_PlugConnector_Name";
+    String plugConnectorDescription = "Undefined_PlugConnector_Description";
+    Transport plugConnectorTransport = new PlugConnectorsTransport();
+    Map<java.lang.String,com.sun.jdi.connect.Connector.Argument> plugConnectorDefaultArguments = new HashMap<java.lang.String,com.sun.jdi.connect.Connector.Argument>();
+
+    /*
+     * Simple implementation of Connector.Argument
+     */
+    public static class TestArgument implements Connector.Argument {
+        String argName;
+        String argLabel;
+        String argDescription;
+        String argStringValue;
+        boolean argMustSpecify;
+
+        public TestArgument(
+                String argName,
+                String argLabel,
+                String argDescription,
+                String argValue,
+                boolean argMustSpecify) {
+
+            this.argName = argName;
+            this.argLabel = argLabel;
+            this.argDescription = argDescription;
+            this.argStringValue = argValue;
+            this.argMustSpecify = argMustSpecify;
+        }
+
+        public String name() {
+            return argName;
+        }
+
+        public String label() {
+            return argLabel;
+        }
+
+        public String description() {
+            return argDescription;
+        }
+
+        public String value() {
+            return argStringValue;
+        }
+
+        public void setValue(String argValue) {
+            this.argStringValue = argValue;
+        }
+
+        public boolean isValid(String argValue) {
+            if ( argValue != null ) {
+                if (argValue.length() > 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public boolean mustSpecify() {
+            return argMustSpecify;
+        }
+    } // end of TestArgument static class
+
+    /*
+     * Simple implementation of Connector.StringArgument
+     */
+    public static class TestStringArgument extends TestArgument implements Connector.StringArgument {
+
+        public TestStringArgument( String argName,
+                        String argLabel,
+                        String argDescription,
+                        String argValue,
+                        boolean argMustSpecify) {
+
+            super(argName, argLabel, argDescription, argValue, argMustSpecify);
+        }
+
+    } // end of TestStringArgument static class
+
+    /*
+     * Simple implementation of Connector.IntegerArgument
+     */
+    public static class TestIntegerArgument extends TestArgument implements Connector.IntegerArgument {
+
+        int argIntValue;
+        int minArgIntValue;
+        int maxArgIntValue;
+
+        public TestIntegerArgument(String argName,
+                        String argLabel,
+                        String argDescription,
+                        int argValue,
+                        int minArgIntValue,
+                        int maxArgIntValue,
+                        boolean argMustSpecify) {
+
+            super(argName, argLabel, argDescription, "" + argValue, argMustSpecify);
+            this.argIntValue = argValue;
+            this.minArgIntValue = minArgIntValue;
+            this.maxArgIntValue = maxArgIntValue;
+
+        }
+
+        public int intValue() {
+            return argIntValue;
+        }
+
+        public boolean isValid(int value) {
+            if ( value >= minArgIntValue && value <= maxArgIntValue ) {
+                return true;
+            }
+            return false;
+        }
+
+        public boolean isValid(String stringValue) {
+            int intValue;
+            try {
+                intValue = Integer.parseInt(stringValue);
+            } catch (NumberFormatException exception) {
+                return false;
+            }
+            return isValid(intValue);
+        }
+
+        public int max() {
+            return maxArgIntValue;
+        }
+
+        public int min() {
+            return minArgIntValue;
+        }
+
+        public void setValue(int value) {
+            argIntValue = value;
+        }
+
+        public String stringValueOf(int value) {
+            return "" + value;
+        }
+
+    } // end of TestIntegerArgument static class
+
+    /*
+     * Simple implementation of Connector.BooleanArgument
+     */
+    public static class TestBooleanArgument extends TestArgument implements Connector.BooleanArgument {
+
+        static final String argStringValueTrue = "true";
+        static final String argStringValueFalse = "false";
+        boolean argBooleanValue;
+
+        public TestBooleanArgument(String argName,
+                        String argLabel,
+                        String argDescription,
+                        boolean argValue,
+                        boolean argMustSpecify) {
+
+            super(argName, argLabel, argDescription,
+                argValue ? argStringValueTrue : argStringValueFalse,
+                argMustSpecify);
+            this.argBooleanValue = argValue;
+
+        }
+
+        public boolean booleanValue() {
+            return argBooleanValue;
+        }
+
+        public boolean isValid(String stringValue) {
+            if ( argStringValueTrue.equals(stringValue) || argStringValueFalse.equals(stringValue) ) {
+                return true;
+            }
+            return false;
+        }
+
+        public void setValue(boolean value) {
+            argBooleanValue = value;
+        }
+
+        public String stringValueOf(boolean value) {
+            if ( value ) {
+                return argStringValueTrue;
+            }
+            return argStringValueFalse;
+        }
+
+    } // end of TestBooleanArgument static class
+
+    /*
+     * Simple implementation of Connector.SelectedArgument
+     */
+    public static class TestSelectedArgument extends TestArgument implements Connector.SelectedArgument {
+
+        List<String> acceptableArgsList;
+
+        public TestSelectedArgument( String argName,
+                        String argLabel,
+                        String argDescription,
+                        String argValue,
+                        List<String> acceptableArgsList,
+                        boolean argMustSpecify) {
+
+            super(argName, argLabel, argDescription, argValue, argMustSpecify);
+            this.acceptableArgsList = acceptableArgsList;
+        }
+
+        public List<String> choices() {
+            return acceptableArgsList;
+        }
+
+        public boolean isValid(String stringValue) {
+
+            return acceptableArgsList.contains(stringValue);
+        }
+
+    } // end of TestSelectedArgument static class
+
+    public PlugConnectors(
+        String plugConnectorName,
+        String plugConnectorDescription,
+        Transport plugConnectorTransport,
+        Map<java.lang.String,com.sun.jdi.connect.Connector.Argument> plugConnectorDefaultArguments
+        ) {
+
+        this.plugConnectorName = plugConnectorName;
+        this.plugConnectorDescription = plugConnectorDescription;
+        this.plugConnectorTransport = plugConnectorTransport;
+        this.plugConnectorDefaultArguments = plugConnectorDefaultArguments;
+    }
+
+    public String name() {
+        return plugConnectorName;
+    }
+
+    public String description() {
+        return plugConnectorDescription;
+    }
+
+    public Transport transport() {
+        return plugConnectorTransport;
+    }
+
+    public Map<java.lang.String,com.sun.jdi.connect.Connector.Argument> defaultArguments() {
+        return plugConnectorDefaultArguments;
+    }
+
+    public VirtualMachine launch(Map<String,? extends Connector.Argument> arguments) throws
+                                IOException,
+                                IllegalConnectorArgumentsException,
+                                VMStartException {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of launch(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public VirtualMachine attach(Map<String,? extends Connector.Argument> arguments) throws
+                                java.io.IOException,
+                                IllegalConnectorArgumentsException {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of attach(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public String startListening(Map<String,? extends Connector.Argument> arguments) throws
+                                java.io.IOException,
+                                IllegalConnectorArgumentsException {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of startListening(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public void stopListening(Map<String,? extends Connector.Argument> arguments) throws
+                                java.io.IOException,
+                                IllegalConnectorArgumentsException {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of stopListening(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+    }
+
+    public VirtualMachine accept(Map<String,? extends Connector.Argument> arguments) throws
+                                java.io.IOException,
+                                IllegalConnectorArgumentsException {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of accept(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public boolean supportsMultipleConnections() {
+
+        String exceptionMessage = "## PlugConnectors: Connector name = '" +
+            plugConnectorName + "';\nNon-authorized call of supportsMultipleConnections() method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return false;
+    }
+
+    public static class PlugConnectorsTransport implements Transport {
+
+        String transportName = "Undefined_Transport_Name";
+
+        public PlugConnectorsTransport() {
+        }
+
+        public PlugConnectorsTransport(String transportName) {
+            this.transportName = transportName;
+        }
+
+        public String name() {
+            return transportName;
+        }
+
+    } // end of PlugConnectorsTransport class
+
+    // Auxiliary general purpose methods for pluggable connectors' tests.
+
+    public static String compareConnectors(
+        String errorLogPrefixHead,
+        String errorLogPrefix,
+        Connector referenceConnector,
+        Connector checkedConnector) {
+
+        String emptyString = "";
+        String errorMessage = emptyString;
+
+        // check that connectors have the same name
+        String referenceConnectorName = referenceConnector.name();
+        String checkedConnectorName = checkedConnector.name();
+        if ( ! referenceConnectorName.equals(checkedConnectorName) ) {
+            errorMessage =  errorMessage +
+                errorLogPrefixHead + "Checked pluggable Connector has unexpected name:\n"
+                + errorLogPrefix + "Expected Connector's name = '" + referenceConnectorName + "'\n"
+                + errorLogPrefix + "Actual Connector's name = '" + checkedConnectorName + "'\n";
+        }
+
+        // check that connectors have the same description
+        String referenceConnectorDescription = referenceConnector.description();
+        String checkedConnectorDescription = checkedConnector.description();
+        if ( ! referenceConnectorDescription.equals(checkedConnectorDescription) ) {
+            errorMessage =  errorMessage +
+                errorLogPrefixHead + "Checked pluggable Connector has unexpected description:\n"
+                + errorLogPrefix + "Expected Connector's description = '" + referenceConnectorDescription + "'\n"
+                + errorLogPrefix + "Actual Connector's description = '" + checkedConnectorDescription + "'\n";
+        }
+
+        // check that connectors have the same transport name
+        String referenceConnectorTransportName = referenceConnector.transport().name();
+        String checkedConnectorTransportName = checkedConnector.transport().name();
+        if ( ! referenceConnectorTransportName.equals(checkedConnectorTransportName) ) {
+            errorMessage =  errorMessage +
+                errorLogPrefixHead + "Checked pluggable Connector has unexpected transport name:\n"
+                + errorLogPrefix + "Expected Connector's transport name = '" + referenceConnectorTransportName + "'\n"
+                + errorLogPrefix + "Actual Connector's transport name = '" + checkedConnectorTransportName + "'\n";
+        }
+
+        // check that connectors have the same number of default arguments
+        int referenceConnectorArgumentsNumber = referenceConnector.defaultArguments().size();
+        int checkedConnectorArgumentsNumber = checkedConnector.defaultArguments().size();
+        if ( referenceConnectorArgumentsNumber != checkedConnectorArgumentsNumber ) {
+            errorMessage =  errorMessage +
+                errorLogPrefixHead + "Checked pluggable Connector has unexpected number of default arguments:\n"
+                + errorLogPrefix + "Expected number of default arguments = '" + referenceConnectorArgumentsNumber + "'\n"
+                + errorLogPrefix + "Actual number of default arguments = '" + checkedConnectorArgumentsNumber + "'\n";
+        }
+
+
+        return errorMessage;
+    }  // end of compareConnectors(...) method
+
+    public static String compareConnectorArguments(
+        String errorLogPrefixHead,
+        String errorLogPrefix,
+        Connector.Argument referenceArgument,
+        Connector.Argument checkedArgument) {
+
+        String emptyString = "";
+        String errorMessage = emptyString;
+
+        if ( referenceArgument == null ) {
+            errorMessage =
+                errorLogPrefixHead + "Reference connector's argument is null!\n";
+        }
+
+        if ( checkedArgument == null ) {
+            errorMessage = errorMessage +
+                errorLogPrefixHead + "Checked connector's argument is null!\n";
+        }
+
+        if ( ! errorMessage.equals(emptyString) ) {
+            return errorMessage;
+        }
+
+        String referenceArgumentName = referenceArgument.name();
+        String checkedArgumentName = checkedArgument.name();
+        if ( ! referenceArgumentName.equals(checkedArgumentName) ) {
+            errorMessage =
+                errorLogPrefixHead + "Checked connector's argument has unexpected name:\n"
+                + errorLogPrefix + "Expected connector's argument name = '" + referenceArgumentName + "'\n"
+                + errorLogPrefix + "Actual connector's argument name = '" + checkedArgumentName + "'";
+            return errorMessage;
+        }
+
+        String referenceArgumentLabel = referenceArgument.label();
+        String checkedArgumentLabel = checkedArgument.label();
+        if ( ! referenceArgumentLabel.equals(checkedArgumentLabel) ) {
+            errorMessage =
+                errorLogPrefixHead + "Checked connector's argument has unexpected label:\n"
+                + errorLogPrefix + "Expected connector's argument label = '" + referenceArgumentLabel + "'\n"
+                + errorLogPrefix + "Actual connector's argument label = '" + checkedArgumentLabel + "'";
+            return errorMessage;
+        }
+
+        String referenceArgumentDescription = referenceArgument.description();
+        String checkedArgumentDescription = checkedArgument.description();
+        if ( ! referenceArgumentDescription.equals(checkedArgumentDescription) ) {
+            errorMessage =
+                errorLogPrefixHead + "Checked connector's argument has unexpected description:\n"
+                + errorLogPrefix + "Expected connector's argument description = '" + referenceArgumentDescription + "'\n"
+                + errorLogPrefix + "Actual connector's argument description = '" + checkedArgumentDescription + "'";
+            return errorMessage;
+        }
+
+        String referenceArgumentValue = referenceArgument.value();
+        String checkedArgumentValue = checkedArgument.value();
+        if ( ! referenceArgumentValue.equals(checkedArgumentValue) ) {
+            errorMessage =
+                errorLogPrefixHead + "Checked connector's argument has unexpected value:\n"
+                + errorLogPrefix + "Expected connector's argument value = '" + referenceArgumentValue + "'\n"
+                + errorLogPrefix + "Actual connector's argument value = '" + checkedArgumentValue + "'";
+            return errorMessage;
+        }
+
+        boolean referenceArgumentMustSpecify = referenceArgument.mustSpecify();
+        boolean checkedArgumentMustSpecify = checkedArgument.mustSpecify();
+        if ( referenceArgumentMustSpecify != checkedArgumentMustSpecify ) {
+            errorMessage =
+                errorLogPrefixHead + "Checked connector's argument has unexpected 'mustSpecify' property:\n"
+                + errorLogPrefix + "Expected connector's argument 'mustSpecify' property = '"
+                    + referenceArgumentMustSpecify + "'\n"
+                + errorLogPrefix + "Actual connector's argument 'mustSpecify' property = '"
+                    + checkedArgumentMustSpecify + "'";
+            return errorMessage;
+        }
+
+        if ( referenceArgument instanceof Connector.IntegerArgument ) {
+
+            int referenceArgumentMin = ((Connector.IntegerArgument)referenceArgument).min();
+            int checkedArgumentMin = ((Connector.IntegerArgument)checkedArgument).min();
+            if ( referenceArgumentMin != checkedArgumentMin ) {
+                errorMessage =
+                    errorLogPrefixHead + "Checked connector's integer argument has unexpected min value:\n"
+                    + errorLogPrefix + "Expected connector's argument min value = "
+                        + referenceArgumentMin + "\n"
+                    + errorLogPrefix + "Actual connector's argument min value = "
+                        + checkedArgumentMin + "\n";
+            }
+
+            int referenceArgumentMax = ((Connector.IntegerArgument)referenceArgument).max();
+            int checkedArgumentMax = ((Connector.IntegerArgument)checkedArgument).max();
+            if ( referenceArgumentMax != checkedArgumentMax ) {
+                errorMessage = errorMessage +
+                    errorLogPrefixHead + "Checked connector's integer argument has unexpected max value:\n"
+                    + errorLogPrefix + "Expected connector's argument max value = "
+                        + referenceArgumentMax + "\n"
+                    + errorLogPrefix + "Actual connector's argument max value = "
+                        + checkedArgumentMax + "\n";
+            }
+
+        }
+
+        if ( referenceArgument instanceof Connector.SelectedArgument ) {
+
+            List referenceArgumentChoices = ((Connector.SelectedArgument)referenceArgument).choices();
+            List checkedArgumentChoices = ((Connector.SelectedArgument)checkedArgument).choices();
+
+            int referenceArgumentChoicesSize = referenceArgumentChoices.size();
+            int checkedArgumentChoicesSize = checkedArgumentChoices.size();
+
+            if ( referenceArgumentChoicesSize != checkedArgumentChoicesSize) {
+                errorMessage = errorMessage +
+                    errorLogPrefixHead + "Checked connector's Selected argument has unexpected choices' size:\n"
+                    + errorLogPrefix + "Expected size = '"
+                        + referenceArgumentChoicesSize + "'\n"
+                    + errorLogPrefix + "Actual size = "
+                        + checkedArgumentChoicesSize;
+                return errorMessage;
+            }
+
+            for (int i=0; i < referenceArgumentChoicesSize; i++) {
+                String referenceArgumentChoice = (String)(referenceArgumentChoices.get(i));
+                if ( ! checkedArgumentChoices.contains(referenceArgumentChoice) ) {
+                    errorMessage = errorMessage +
+                        errorLogPrefixHead + "Checked connector's Selected argument has NOT expected choices' element:\n"
+                        + errorLogPrefix + "Expected choices' element = '"
+                            + referenceArgumentChoice + "'\n";
+                }
+
+                String checkedArgumentChoice = (String)(checkedArgumentChoices.get(i));
+                if ( ! referenceArgumentChoices.contains(checkedArgumentChoice) ) {
+                    errorMessage = errorMessage +
+                        errorLogPrefixHead + "Checked connector's Selected argument has unexpected choices' element:\n"
+                        + errorLogPrefix + "Unexpected choices' element = '"
+                            + checkedArgumentChoice + "'\n";
+                }
+            }
+        }
+        return errorMessage;
+    }  // end of compareConnectorArguments(...) method
+
+    public static Connector.Argument getConnectorDefaultArgument(
+            Connector connector,
+            String argumentName) {
+
+        Connector.Argument foundArgument = null;
+
+        Map connectorDefaultArguments = connector.defaultArguments();
+        Object[] defaultArgumentsArray = connectorDefaultArguments.values().toArray();
+
+        for (int i=0; i < defaultArgumentsArray.length; i++) {
+            Connector.Argument connectorArgument = (Connector.Argument)defaultArgumentsArray[i];
+            if ( argumentName.equals(connectorArgument.name()) ) {
+                foundArgument = connectorArgument;
+                break;
+            }
+        }
+        return foundArgument;
+    }
+
+} // end of PlugConnectors class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/PlugTransportService.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A Super class for Transport Services used by
+ * nsk/jdi/PlugConnectors tests
+ */
+
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+import com.sun.jdi.connect.*;
+import com.sun.jdi.connect.spi.*;
+import java.io.*;
+import java.util.*;
+
+public class PlugTransportService extends TransportService {
+
+    String plugTransportServiceName = "Undefined_PlugTransportService_Name";
+    String plugTransportServiceDescription = "Undefined_PlugTransportService_Description";
+    TransportService.Capabilities plugTransportServiceCapabilities = new TestCapabilities();
+
+    /*
+     * Simple implementation of TransportService.Capabilities
+     */
+    public static class TestCapabilities extends TransportService.Capabilities {
+        boolean supportsAcceptTimeout = false;
+        boolean supportsAttachTimeout = false;
+        boolean supportsHandshakeTimeout = false;
+        boolean supportsMultipleConnections = false;
+
+        public TestCapabilities() {
+        }
+
+        public TestCapabilities(
+                boolean supportsAcceptTimeout,
+                boolean supportsAttachTimeout,
+                boolean supportsHandshakeTimeout,
+                boolean supportsMultipleConnections) {
+
+            this.supportsAcceptTimeout = supportsAcceptTimeout;
+            this.supportsAttachTimeout = supportsAttachTimeout;
+            this.supportsHandshakeTimeout = supportsHandshakeTimeout;
+            this.supportsMultipleConnections = supportsMultipleConnections;
+        }
+
+        public boolean supportsAcceptTimeout() {
+            return supportsAcceptTimeout;
+        }
+
+        public boolean supportsAttachTimeout() {
+            return supportsAttachTimeout;
+        }
+
+        public boolean supportsHandshakeTimeout() {
+            return supportsHandshakeTimeout;
+        }
+
+        public boolean supportsMultipleConnections() {
+            return supportsMultipleConnections;
+        }
+
+    } // end of TestCapabilities static class
+
+    /*
+     * Simple implementation of TransportService.ListenKey
+     */
+    public static class TestListenKey extends TransportService.ListenKey {
+        String address = null;
+
+        public TestListenKey() {
+        }
+
+        public TestListenKey(String address) {
+
+            this.address = address;
+        }
+
+        public String address() {
+            return address;
+        }
+
+    } // end of TestListenKey static class
+
+    public PlugTransportService() {
+    }
+
+    public PlugTransportService(
+        String plugTransportServiceName,
+        String plugTransportServiceDescription,
+        TransportService.Capabilities plugTransportServiceCapabilities
+        ) {
+
+        this.plugTransportServiceName = plugTransportServiceName;
+        this.plugTransportServiceDescription = plugTransportServiceDescription;
+        this.plugTransportServiceCapabilities = plugTransportServiceCapabilities;
+    }
+
+    public String name() {
+        return plugTransportServiceName;
+    }
+
+    public String description() {
+        return plugTransportServiceDescription;
+    }
+
+    public TransportService.Capabilities capabilities() {
+        return plugTransportServiceCapabilities;
+    }
+
+    public Connection attach(
+            String address,
+            long attachTimeout,
+            long handshakeTimeout) throws IOException {
+
+        String exceptionMessage = "## PlugTransportService: TransportService name = '" +
+            plugTransportServiceName + "';\nNon-authorized call of attach(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public TransportService.ListenKey startListening(String address) throws IOException {
+
+        String exceptionMessage = "## PlugTransportService: TransportService name = '" +
+            plugTransportServiceName + "';\nNon-authorized call of startListening(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public TransportService.ListenKey startListening() throws IOException {
+
+        String exceptionMessage = "## PlugTransportService: TransportService name = '" +
+            plugTransportServiceName + "';\nNon-authorized call of startListening() method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    public void stopListening(TransportService.ListenKey listenKey) throws IOException {
+
+        String exceptionMessage = "## PlugTransportService: TransportService name = '" +
+            plugTransportServiceName + "';\nNon-authorized call of stopListening() method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+    }
+
+    public Connection accept(
+            TransportService.ListenKey listenKey,
+            long acceptTimeout,
+            long handshakeTimeout) throws IOException {
+
+        String exceptionMessage = "## PlugTransportService: TransportService name = '" +
+            plugTransportServiceName + "';\nNon-authorized call of accept(...) method!";
+
+        if ( true ) {
+            throw new RuntimeException(exceptionMessage);
+        }
+
+        return null;
+    }
+
+    /*
+     * Simple implementation of Connection
+     */
+    public static class PlugTransportServiceConnection extends Connection {
+
+        public void close() throws IOException {
+            String exceptionMessage =
+                "## PlugTransportConnection: \nNon-authorized call of close() method!";
+
+            if ( true ) {
+                throw new RuntimeException(exceptionMessage);
+            }
+        }
+
+        public boolean isOpen() {
+            String exceptionMessage =
+                "## PlugTransportConnection: \nNon-authorized call of isOpen() method!";
+
+            if ( true ) {
+                throw new RuntimeException(exceptionMessage);
+            }
+            return false;
+        }
+
+        public byte[] readPacket() throws IOException {
+            String exceptionMessage =
+                "## PlugTransportConnection: \nNon-authorized call of readPacket() method!";
+
+            if ( true ) {
+                throw new ClosedConnectionException(exceptionMessage);
+            }
+
+            if ( true ) {
+                throw new ClosedConnectionException();
+            }
+
+            return null;
+        }
+
+        public void writePacket(byte[] pkt) throws IOException {
+            String exceptionMessage =
+                "## PlugTransportConnection: \nNon-authorized call of writePacket(...) method!";
+
+            if ( true ) {
+                throw new ClosedConnectionException(exceptionMessage);
+            }
+
+            if ( true ) {
+                throw new ClosedConnectionException();
+            }
+
+        }
+
+    } // end of PlugTransportServiceConnection class
+
+} // end of PlugTransportService class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.IOException;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
+import nsk.share.Consts;
+
+/*
+ * This class is intended for execution several JDI tests in single VM and used together with nsk.share.jdi.SerialExecutionDebugger
+ *
+ * SerialExecutionDebuggee handles 2 commands:
+ *  - COMMAND_EXECUTE_DEBUGGEE:<debuggee_class_name> :
+ *  initialize 'currentDebuggee' with instance of class 'debuggee_class_name'(this class should
+ *  be subclass of nsk.share.jpda.AbstractDebugeeTest) and execute it's method doTest()
+ *
+ *  - COMMAND_CLEAR_DEBUGGEE
+ *  set 'currentDebuggee' to null
+ *
+ *  For more detailed description of serial test execution see SerialExecutionDebugger
+ */
+public class SerialExecutionDebuggee extends AbstractJDIDebuggee {
+    public static void main(String args[]) {
+        new SerialExecutionDebuggee().doTest(args);
+    }
+
+    // command:<debuggee_class_name>[ debugee_parameters]
+    public static final String COMMAND_EXECUTE_DEBUGGEE = "COMMAND_EXECUTE_DEBUGGEE";
+
+    public static final String COMMAND_CLEAR_DEBUGGEE = "COMMAND_CLEAR_DEBUGGEE";
+
+    private AbstractJDIDebuggee currentDebuggee;
+
+    public boolean parseCommand(String command) {
+        if (super.parseCommand(command))
+            return true;
+
+        if (command.startsWith(COMMAND_EXECUTE_DEBUGGEE)) {
+            String debuggeeClassName = null;
+
+            try {
+                StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command));
+                tokenizer.resetSyntax();
+                tokenizer.wordChars(Integer.MIN_VALUE, Integer.MAX_VALUE);
+                tokenizer.whitespaceChars(':', ':');
+
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD) {
+                    log.complain("Invalid command format: " + command);
+                    System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                }
+
+                debuggeeClassName = tokenizer.sval;
+            } catch (IOException e) {
+                log.complain("Invalid command format: " + command);
+                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+            }
+
+            try {
+                // parse debuggee parameters
+                String[] debuggeeParameters = {};
+
+                int index = debuggeeClassName.indexOf(' ');
+
+                if (index > 0) {
+                    debuggeeParameters = debuggeeClassName.substring(index).split(" ");
+                    log.display("Debuggee parameters: " + debuggeeClassName.substring(index));
+                    debuggeeClassName = debuggeeClassName.substring(0, index);
+                }
+
+                // create debuggee object
+                Class debuggeeClass = Class.forName(debuggeeClassName);
+
+                if (!AbstractJDIDebuggee.class.isAssignableFrom(debuggeeClass)) {
+                    log.complain("Invalid debugee class: " + debuggeeClass);
+                    System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                }
+
+                currentDebuggee = (AbstractJDIDebuggee) debuggeeClass.newInstance();
+
+                // pass to the current debuggee already created objects:
+                // argHandler, log, pipe
+                currentDebuggee.initDebuggee(argHandler, log, pipe, debuggeeParameters, false);
+            } catch (Exception e) {
+                log.complain("Unexpected exception during debuggee initialization: " + e);
+                e.printStackTrace(log.getOutStream());
+                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+            }
+
+            try {
+                // current debuggee performs test
+                currentDebuggee.doTest();
+
+                if (currentDebuggee.getSuccess()) {
+                    log.display("Debuggee " + currentDebuggee + " finished successfully");
+                } else {
+                    setSuccess(false);
+                    log.complain("Debuggee " + currentDebuggee + "finished with errors");
+                }
+
+                return true;
+            } catch (Exception e) {
+                log.complain("Unexpected exception during debuggee execution: " + e);
+                e.printStackTrace(log.getOutStream());
+                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+            }
+        } else if (command.equals(COMMAND_CLEAR_DEBUGGEE)) {
+            currentDebuggee = null;
+
+            return true;
+        }
+
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/SerialExecutionDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import nsk.share.Consts;
+import nsk.share.TestBug;
+import nsk.share.jpda.AbstractDebuggeeTest;
+import java.io.*;
+import java.util.*;
+
+/*
+ * This class serial executes several JDI tests based on nsk.share.jdi.TestDebuggerType2 in single VM
+ * SerialExecutionDebugger is used together with SerialExecutionDebuggee, execution process is following:
+ *
+ *  - SerialExecutionDebugger reads tests to execute from input file, test description is debugger class name and test's parameters,
+ *  if 'shuffle' option is specified in input file debugger executes tests in random order (input file should contain line "OPTIONS:shuffle").
+ *  SerialExecutionDebugger can execute tests several times in loop, number of iterations should be specified in input file in following manner:
+ *  OPTIONS:iterations <iterations_number>.
+ *
+ *  - SerialExecutionDebugger starts debuggee VM with main class SerialExecutionDebuggee,
+ *  initializes IOPipe and 'debuggee' object which represents debuggee VM
+ *
+ *  - for each test from input file:
+ *
+ *      - SerialExecutionDebugger creates object of current debugger and initializes it with already created pipe and debuggee
+ *      - SerialExecutionDebugger sends command to SerialExecutionDebuggee:  'COMMAND_EXECUTE_DEBUGGEE <CurrentDebuggeeName>'
+ *      (CurrentDebuggeeName name should provide current debugger), and waits READY signal from debuggee
+ *      - SerialExecutionDebuggee parses received command, extracts debugee name, creates object of current debuggee, which should be
+ *      subclass of nsk.share.jpda.AbstractDebuggeeTestName
+ *      - SerialExecutionDebuggee executes current debuggee's method 'doTest()', in this method debuggee sends signal READY
+ *      and waits debugger command
+ *      - SerialExecutionDebugger receives signal READY and executes current debugger's method 'doTest()', in
+ *      this method debugger should perform test
+ *      - when debugger method doTest() finishes SerialExecutionDebugger checks is this test passed or failed and
+ *      sends command QUIT to the current debuggee, and when current debuggee finishes sends command 'COMMAND_CLEAR_DEBUGGEE' to the SerialExecutionDebuggee,
+ *      after this command SerialExecutionDebugger and SerialExecutionDebuggee ready to execute next test
+ *
+ *  - when all tests was executed SerialExecutionDebugger sends command QUIT to the SerialExecutionDebuggee and exits
+ *
+ * SerialExecutionDebugger requires "-configFile <ini-file>" parameter, <ini-file> - file with list of tests for execution
+ */
+public class SerialExecutionDebugger extends TestDebuggerType2 {
+    static public void main(String[] args) {
+        System.exit(Consts.JCK_STATUS_BASE + new SerialExecutionDebugger().runIt(args, System.out));
+    }
+
+    public String debuggeeClassName() {
+        return SerialExecutionDebuggee.class.getName();
+    }
+
+    // contains test's debugger class name and test parameters
+    static class Test {
+        public Test(String debuggerClassName, String[] arguments) {
+            this.debuggerClassName = debuggerClassName;
+            this.arguments = arguments;
+        }
+
+        public String argumentsToString() {
+            String result = "";
+
+            for (String argument : arguments)
+                result += argument + " ";
+
+            return result;
+        }
+
+        String debuggerClassName;
+
+        String arguments[];
+    }
+
+    private Test tests[];
+
+    // how many times execute tests
+    private int iterations = 1;
+
+    // requires "-configFile <ini-file>" parameter, <ini-file> - file with list
+    // of tests for execution
+    protected String[] doInit(String args[], PrintStream out) {
+        args = super.doInit(args, out);
+
+        String configFileName = null;
+
+        ArrayList<String> standardArgs = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-configFile") && (i < args.length - 1)) {
+                configFileName = args[i + 1];
+                i++;
+            } else
+                standardArgs.add(args[i]);
+        }
+
+        if (configFileName == null) {
+            throw new TestBug("Config file wasn't specified (use option -configFile <file name>)");
+        }
+
+        tests = parseConfigFile(configFileName);
+
+        if (tests.length == 0)
+            throw new TestBug("Tests to run were not specified");
+
+        return standardArgs.toArray(new String[] {});
+    }
+
+    // read test names and test parameters from ini-file
+    private Test[] parseConfigFile(String fileName) {
+        List<Test> result = new ArrayList<Test>();
+
+        boolean shuffle = false;
+
+        try {
+            File file = new File(fileName);
+
+            LineNumberReader lineReader = new LineNumberReader(new FileReader(file));
+
+            String line = null;
+
+            while ((line = lineReader.readLine()) != null) {
+                // skip empty lines and comments started with '#"
+                if (line.length() == 0 || line.startsWith("#"))
+                    continue;
+
+                if (line.startsWith("OPTIONS:")) {
+                    String arguments[] = line.substring(8).split(" ");
+
+                    for (int i = 0; i < arguments.length; i++) {
+                        if (arguments[i].equalsIgnoreCase("shuffle"))
+                            shuffle = true;
+                        else if (arguments[i].equalsIgnoreCase("iterations") && (i < (arguments.length - 1))) {
+                            iterations = Integer.parseInt(arguments[i + 1]);
+                            i++;
+                        }
+                    }
+
+                    continue;
+                }
+
+                StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(line));
+                tokenizer.resetSyntax();
+                tokenizer.wordChars(Integer.MIN_VALUE, Integer.MAX_VALUE);
+                tokenizer.whitespaceChars(' ', ' ');
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid ini file format");
+
+                String testClassName = tokenizer.sval;
+                List<String> parameters = new ArrayList<String>();
+
+                int token;
+                while ((token = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
+                    if (token == StreamTokenizer.TT_WORD) {
+                        if (tokenizer.sval.equals("$CLASSPATH"))
+                            parameters.add(classpath);
+                        else
+                            parameters.add(tokenizer.sval);
+                    }
+
+                    if (token == StreamTokenizer.TT_NUMBER) {
+                        parameters.add("" + tokenizer.nval);
+                    }
+                }
+
+                result.add(new Test(testClassName, parameters.toArray(new String[] {})));
+            }
+
+        } catch (IOException e) {
+            throw new TestBug("Exception during config file parsing: " + e);
+        }
+
+        if (shuffle) {
+            if (testWorkDir == null)
+                throw new TestBug("Debugger requires -testWorkDir parameter");
+
+            Collections.shuffle(result);
+
+            // save resulted tests sequence in file (to simplify reproducing)
+            try {
+                File file = new File(testWorkDir + File.separator + "run.tests");
+                file.createNewFile();
+
+                PrintWriter writer = new PrintWriter(new FileWriter(file));
+
+                for (Test test : result) {
+                    writer.println(test.debuggerClassName + " " + test.argumentsToString());
+                }
+
+                writer.close();
+            } catch (IOException e) {
+                throw new TestBug("Unexpected IOException: " + e);
+            }
+        }
+
+        System.out.println("Tests execution order: ");
+        for (Test test : result) {
+            System.out.println(test.debuggerClassName + " " + test.argumentsToString());
+        }
+
+        return result.toArray(new Test[] {});
+    }
+
+    public void doTest() {
+
+        stresser.start(iterations);
+
+        try {
+            if (iterations == 1) {
+                /*
+                 * Since many test couldn't be run in single VM twice and test config specifies only 1 iteration don't
+                 * multiple iterations by iterations factor and execute tests once (not depending on iterations factor)
+                 */
+                executeTests();
+            } else {
+                while (stresser.continueExecution()) {
+                    if (!executeTests()) {
+                        // if error occured stop execution
+                        break;
+                    }
+                }
+            }
+        } finally {
+            stresser.finish();
+        }
+    }
+
+    boolean executeTests() {
+        // maximum execution time of single test
+        long maxExecutionTime = 0;
+
+        for (Test test : tests) {
+            long testStartTime = System.currentTimeMillis();
+
+            TestDebuggerType2 debugger = null;
+
+            try {
+                // create debugger object
+                Class debuggerClass = Class.forName(test.debuggerClassName);
+
+                if (!TestDebuggerType2.class.isAssignableFrom(debuggerClass)) {
+                    setSuccess(false);
+                    log.complain("Invalid debugger class: " + debuggerClass);
+                    return false;
+                }
+
+                // init test debugger, pass to the debugger already created
+                // objects: argHandler, log, pipe, debuggee, vm
+                debugger = (TestDebuggerType2) debuggerClass.newInstance();
+                debugger.initDebugger(argHandler, log, pipe, debuggee, vm);
+                debugger.doInit(test.arguments, System.out);
+            } catch (Exception e) {
+                setSuccess(false);
+                log.complain("Unexpected exception during debugger initialization: " + e);
+                e.printStackTrace(log.getOutStream());
+
+                return false;
+            }
+
+            log.display("Execute debugger: " + debugger);
+
+            // send command to the SerialExecutionDebuggee (create debuggee
+            // object)
+            pipe.println(SerialExecutionDebuggee.COMMAND_EXECUTE_DEBUGGEE + ":" + debugger.debuggeeClassName());
+
+            // wait first READY from AbstractDebuggeeTest.doTest() (debuggee
+            // sends this command when it was initialized and ready for
+            // test)
+            if (!isDebuggeeReady())
+                return false;
+
+            try {
+                // here debuggee should be ready for test and current
+                // debugger may perform test
+                debugger.doTest();
+
+                if (debugger.getSuccess()) {
+                    log.display("Debugger " + debugger + " finished successfully");
+                } else {
+                    setSuccess(false);
+                    log.complain("Debugger " + debugger + " finished with errors");
+                }
+            } catch (TestBug testBug) {
+                setSuccess(false);
+                log.complain("Test bug in " + debugger + ": " + testBug);
+                testBug.printStackTrace(log.getOutStream());
+            } catch (Throwable t) {
+                setSuccess(false);
+                log.complain("Unexpected exception during test execution(debugger: " + debugger + "): " + t);
+                t.printStackTrace(log.getOutStream());
+            }
+
+            // send QUIT command to the current debuggee
+            pipe.println(AbstractDebuggeeTest.COMMAND_QUIT);
+
+            if (!isDebuggeeReady())
+                return false;
+
+            // send command to the SerialExecutionDebuggee
+            pipe.println(SerialExecutionDebuggee.COMMAND_CLEAR_DEBUGGEE);
+
+            if (!isDebuggeeReady())
+                return false;
+
+            long testExecutionTime = System.currentTimeMillis() - testStartTime;
+
+            if (testExecutionTime > maxExecutionTime)
+                maxExecutionTime = testExecutionTime;
+
+            if (maxExecutionTime > stresser.getTimeLeft()) {
+                log.display("WARNING: stop test execution because of timeout " +
+                                "(max execution time for single test: " + maxExecutionTime + ", time left: " + stresser.getTimeLeft() + ")");
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestClass1.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+/*
+ * Empty class, used to be sure that there are no instances of this class in target VM
+ */
+public class TestClass1 {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestClass2.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+/*
+ * Empty class, used to be sure that there are no instances of this class in target VM
+ * Used in tests where subclass of test class is needed
+ */
+public class TestClass2 extends TestClass1 {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestDebuggerType1.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+
+import java.io.*;
+
+import nsk.share.*;
+
+/**
+ * This class is a template for test debugger.
+ * It bases on some existed tests for testing of
+ * JDI requests and events.
+ *
+ * Requirements for a test debugger which extends
+ * this template are as folllows:
+ *    - the subclass must have 'main' and 'run' methods
+ *      defined like:
+ *           public static void main (String argv[]) {
+ *               System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
+ *           }
+ *
+ *           public static int run (String argv[], PrintStream out) {
+ *               debuggeeName = <DEBUGGEE_NAME_AS_STRING>;
+ *               return new filter001().runThis(argv, out);
+ *           }
+ *
+ *    - the subclass must implement 'testRun' method
+ *      which must contain checkings of all test's assertions.
+ */
+public abstract class TestDebuggerType1 {
+
+    protected static int waitTime;
+    protected static int testExitCode = Consts.TEST_PASSED;
+
+    protected static Binder              binder;
+    protected static Debugee             debuggee;
+    protected static VirtualMachine      vm;
+    protected static ArgumentHandler     argsHandler;
+    protected static Log                 log;
+    protected static String              debuggeeName; /* must be assigned in a subclass */
+    protected static ReferenceType       debuggeeClass;
+
+    protected static EventRequestManager eventRManager;
+    protected static EventHandler        eventHandler;
+    protected static BreakpointRequest   bpRequest  /* communication breakpoint */;
+    protected static volatile int        bpCount;
+
+    protected static void display(String message) {
+        log.display("debugger> " + message);
+    }
+
+    protected static void complain(String message) {
+        log.complain("debugger> " + message);
+    }
+
+    /**
+     * Should be used in test debugger when assertion failed.
+     */
+    protected static void setFailedStatus(String message) {
+        complain(message);
+        testExitCode = Consts.TEST_FAILED;
+    }
+
+    protected int runThis (String argv[], PrintStream out) {
+
+        argsHandler  = new ArgumentHandler(argv);
+        log          = new Log(out, argsHandler);
+        binder       = new Binder(argsHandler, log);
+        waitTime     = argsHandler.getWaitTime() * 60000;
+
+        try {
+            debuggee = binder.bindToDebugee(debuggeeName);
+            debuggee.redirectStdout(log, Debugee.DEBUGEE_STDERR_LOG_PREFIX);
+            vm = debuggee.VM();
+            eventRManager = vm.eventRequestManager();
+
+            eventHandler = new EventHandler(debuggee, log);
+            eventHandler.startListening();
+
+            debuggeeClass = waitForClassPrepared(debuggeeName);
+
+            /* A debuggee class must define 'methodForCommunication'
+             * method and invoke it in points of synchronization
+             * with a debugger.
+             */
+            setCommunicationBreakpoint(debuggeeClass,"methodForCommunication");
+
+            display("TESTING BEGINS");
+
+            // after waitForClassPrepared() main debuggee thread is suspended, resume it before test start
+            display("RESUME DEBUGGEE VM");
+            vm.resume();
+
+            testRun();
+
+            display("TESTING ENDS");
+
+            display("Waiting for debuggee's exit...");
+            eventHandler.waitForVMDisconnect();
+
+            int status = EventHandler.getStatus();
+            if (status != 0) {
+                setFailedStatus("Event handler returned unexpected exit status: " +  status);
+            } else {
+                display("Event handler thread exited.");
+            }
+
+            debuggee.endDebugee();
+            status = debuggee.getStatus();
+            if (status != (Consts.TEST_PASSED + Consts.JCK_STATUS_BASE)) {
+                setFailedStatus("Debuggee returned unexpected exit status: " +  status);
+            } else {
+                display("Debuggee PASSED.");
+            }
+
+        } catch (VMDisconnectedException e) {
+            setFailedStatus("Unexpected VMDisconnectedException");
+            e.printStackTrace(log.getOutStream());
+            throw new Failure(e.getMessage());
+
+        } catch (Exception e) {
+            setFailedStatus("Unexpected exception : " + e.getMessage());
+            e.printStackTrace(log.getOutStream());
+            display("Forcing debuggee to exit...");
+            vm.exit(Consts.TEST_PASSED + Consts.JCK_STATUS_BASE);
+        }
+
+        return testExitCode;
+    }
+
+    /**
+     * This method which be implemented in all test debuggers
+     * and must contain checking of test assertions.
+     */
+    protected abstract void testRun();
+
+    /**
+     * Waits until debuggee class is prepared.
+     *
+     */
+    private ReferenceType waitForClassPrepared(String className) {
+        ClassPrepareRequest cpRequest = eventRManager.createClassPrepareRequest();
+        cpRequest.setSuspendPolicy( EventRequest.SUSPEND_EVENT_THREAD);
+        cpRequest.addClassFilter(className);
+
+        ClassPrepareEvent event = (ClassPrepareEvent)eventHandler.waitForRequestedEvent(
+                                       new EventRequest[]{cpRequest}, waitTime, true);
+        ReferenceType refType = event.referenceType();
+        if (!refType.name().equals(className))
+            throw new Failure("Unexpected class name for received ClassPrepareEvent: " + refType.name() +
+                              "\n\texpected name: " + debuggeeName);
+        display("Received ClassPrepareEvent for debuggee class: " + refType.name());
+        return refType;
+    };
+
+    /**
+     * Sets up breakpoint request which serves for synchronization
+     * between debugger and debuggee.
+     *
+     */
+    private void setCommunicationBreakpoint(ReferenceType refType, String methodName) {
+        Method method = debuggee.methodByName(refType, methodName);
+        Location location = null;
+        try {
+            location = method.allLineLocations().get(0);
+        } catch (AbsentInformationException e) {
+            throw new Failure(e);
+        }
+        bpRequest = debuggee.makeBreakpoint(location);
+
+        bpRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
+        bpRequest.putProperty("number", "zero");
+        bpRequest.enable();
+
+        eventHandler.addListener(
+             new EventHandler.EventListener() {
+                 public boolean eventReceived(Event event) {
+                    if (event instanceof BreakpointEvent && bpRequest.equals(event.request())) {
+                        synchronized(eventHandler) {
+                            display("Received communication breakpoint event.");
+                            bpCount++;
+                            eventHandler.notifyAll();
+                        }
+                        return true;
+                    }
+                    return false;
+                 }
+             }
+        );
+    }
+
+    /**
+     * Waits for synchronization breakpoint event and checks
+     * up if there are more test case to check.
+     *
+     * Note: debuggee VM shouldn't be suspended when this method
+     * is called
+     *
+     * @return true if there are more test case to check,
+     *          false otherwise or debuggee is disconnected.
+     */
+    protected boolean shouldRunAfterBreakpoint() {
+        display("shouldRunAfterBreakpoint: entered");
+        boolean shouldRun = true;
+
+        long timeToFinish = System.currentTimeMillis() + waitTime;
+        long timeLeft = waitTime;
+        synchronized(eventHandler) {
+            while (!EventHandler.isDisconnected() && bpCount <= 0 && timeLeft > 0) {
+                display("shouldRunAfterBreakpoint: waiting for breakpoint event during 1 sec.");
+                try {
+                    eventHandler.wait(1000);
+                } catch (InterruptedException e) {
+                    throw new Failure(e);
+                }
+                timeLeft = timeToFinish - System.currentTimeMillis();
+            }
+        }
+        if (timeLeft <= 0 && bpCount <= 0) {
+            setFailedStatus("shouldRunAfterBreakpoint: had not received breakpoint event during waitTime.");
+            shouldRun = false;
+
+        } else if (bpCount > 0) {
+            display("shouldRunAfterBreakpoint: received breakpoint event.");
+            bpCount--;
+        }
+
+        if (!EventHandler.isDisconnected()) {
+            try {
+                int instruction = ((IntegerValue)
+                                   (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value();
+
+                if (instruction == 0) {
+                    display("shouldRunAfterBreakpoint: received instruction from debuggee to finish.");
+                    shouldRun = false;
+                }
+            } catch (VMDisconnectedException e) {
+                shouldRun = false;
+            }
+        } else {
+            shouldRun = false;
+        }
+
+        if (shouldRun) {
+            display("shouldRunAfterBreakpoint: exited with true.");
+        } else {
+            display("shouldRunAfterBreakpoint: exited with false.");
+        }
+        return shouldRun;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestDebuggerType2.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.io.*;
+import java.util.*;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+import com.sun.jdi.request.*;
+import nsk.share.*;
+import nsk.share.jpda.*;
+import nsk.share.test.StressOptions;
+import nsk.share.test.Stresser;
+
+/*
+ *  Class can be used as base debugger class in jdi tests.
+ *  Class contains common method for initializing log, debugee, pipe, vm, and several common auxiliary methods.
+ *  Sublcass should implement doTest() and, if needed, doInit(parse command line parameters) and canRunTest(check if VM support tested functionality)
+ */
+public class TestDebuggerType2 {
+    public class EventListenerThread extends Thread {
+        private EventRequest eventRequest;
+
+        private Event event;
+
+        private Wicket wicket = new Wicket();
+
+        public EventListenerThread(EventRequest eventRequest) {
+            this.eventRequest = eventRequest;
+        }
+
+        public void run() {
+            wicket.unlock();
+
+            try {
+                event = debuggee.waitingEvent(eventRequest, argHandler.getWaitTime() * 60000);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        public void waitStartListen() {
+            wicket.waitFor();
+        }
+
+        public Event getEvent() {
+            try {
+                // wait when EventListenerThread complete execution
+                this.join();
+            } catch (InterruptedException e) {
+                setSuccess(false);
+                log.complain("Unexpected exception: " + e);
+            }
+
+            return event;
+        }
+    }
+
+    protected ArgumentHandler argHandler;
+
+    protected Log log;
+
+    protected IOPipe pipe;
+
+    protected Debugee debuggee;
+
+    protected VirtualMachine vm;
+
+    /*
+     * this method is called from nsk.share.jdi.SerialExecutionDebugger to set for debugger
+     * already created instances of ArgumentHandler, Log, IOPipe, Debugee, VirtualMachine
+     */
+    public void initDebugger(ArgumentHandler argHandler, Log log, IOPipe pipe, Debugee debuggee, VirtualMachine vm) {
+        this.argHandler = argHandler;
+        this.log = log;
+        this.pipe = pipe;
+        this.debuggee = debuggee;
+        this.vm = vm;
+    }
+
+    private boolean success = true;
+
+    protected void setSuccess(boolean value) {
+        success = value;
+    }
+
+    protected boolean getSuccess() {
+        return success;
+    }
+
+    // class name used during initialization
+    protected String debuggeeClassName() {
+        return null;
+    }
+
+    // select only class name if debuggeeClassName() returns className + debuggee parameters
+    protected String debuggeeClassNameWithoutArgs() {
+        String className = debuggeeClassName();
+
+        int index = className.indexOf(' ');
+        if (index > 0) {
+            return className.substring(0, index);
+        } else
+            return className;
+    }
+
+    protected String classpath;
+
+    protected String testWorkDir;
+
+    // initialize test and remove unsupported by nsk.share.jdi.ArgumentHandler arguments
+    // (ArgumentHandler constructor throws BadOption exception if command line contains unrecognized by ArgumentHandler options)
+    // support -testClassPath parameter: path to find classes for custom classloader in debuggee VM
+    // (note that in this method stressOptions and stresser are created, so if subclasses override this method
+    // overrided version should first call super.doInit())
+    protected String[] doInit(String args[], PrintStream out) {
+        stressOptions = new StressOptions(args);
+        stresser = new Stresser(stressOptions);
+
+        ArrayList<String> standardArgs = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-testClassPath") && (i < args.length - 1)) {
+                classpath = args[i + 1];
+                i++;
+            } else if (args[i].equals("-testWorkDir") && (i < args.length - 1)) {
+                testWorkDir = args[i + 1];
+
+                if (testWorkDir.endsWith(File.separator)) {
+                    testWorkDir = testWorkDir.substring(0, testWorkDir.length() - 1);
+                }
+
+                i++;
+            } else
+                standardArgs.add(args[i]);
+        }
+
+        return standardArgs.toArray(new String[] {});
+    }
+
+    protected void doTest() {
+        setSuccess(false);
+        throw new TestBug("TEST BUG: method doTest not implemented");
+    }
+
+    protected Stresser stresser;
+    protected StressOptions stressOptions;
+
+    // initialize log, debuggee, pipe
+    public void init(String args[], PrintStream out) {
+        argHandler = new ArgumentHandler(doInit(args, out));
+        log = new Log(out, argHandler);
+        Binder binder = new Binder(argHandler, log);
+        debuggee = binder.bindToDebugee(debuggeeClassName());
+        pipe = debuggee.createIOPipe();
+        debuggee.redirectStderr(log, "Debugger.err> ");
+        vm = debuggee.VM();
+        debuggee.resume();
+
+        String command = pipe.readln();
+
+        if (!command.equals(AbstractDebuggeeTest.COMMAND_READY)) {
+            setSuccess(false);
+            log.complain("TEST BUG: unknown debuggee's command: " + command);
+        }
+    }
+
+    // check that vm support tested functions
+    protected boolean canRunTest() {
+        return true;
+    }
+
+    // send quit command to debuggee
+    protected void quitDebuggee() {
+        pipe.println(AbstractDebuggeeTest.COMMAND_QUIT);
+        debuggee.waitFor();
+
+        int debStat = debuggee.getStatus();
+
+        if (debStat != (Consts.JCK_STATUS_BASE + Consts.TEST_PASSED)) {
+            setSuccess(false);
+            log.complain("TEST FAILED: debuggee's process finished with status: " + debStat);
+        } else
+            log.display("Debuggee's process finished with status: " + debStat);
+
+    }
+
+    // init test, execute test, quit debuggee
+    protected int runIt(String args[], PrintStream out) {
+        init(args, out);
+
+        try {
+            if (canRunTest())
+                doTest();
+        } catch (TestBug testBug) {
+            setSuccess(false);
+            log.complain("Test bug: " + testBug);
+            testBug.printStackTrace(log.getOutStream());
+        } catch (Throwable t) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + t);
+            t.printStackTrace(log.getOutStream());
+        }
+
+        quitDebuggee();
+
+        if (getSuccess()) {
+            log.display("TEST PASSED");
+            return Consts.TEST_PASSED;
+        } else {
+            log.display("TEST FAILED");
+            return Consts.TEST_FAILED;
+        }
+    }
+
+    // check the debuggee completed pervious command and is ready for new one
+    protected boolean isDebuggeeReady() {
+        String command = pipe.readln();
+
+        if (!command.equals(AbstractDebuggeeTest.COMMAND_READY)) {
+            setSuccess(false);
+            log.complain("TEST BUG: unknown debuggee's command: " + command);
+
+            return false;
+        }
+
+        return true;
+    }
+
+    // find in debuggee VM instance of object with given class and check
+    // that there is only one instance of this class
+    protected ObjectReference findSingleObjectReference(String className) {
+        ReferenceType referenceType = debuggee.classByName(className);
+
+        if (referenceType == null)
+            throw new TestBug("There is no class '" + className + "' in debuggee");
+
+        List<ObjectReference> instances = referenceType.instances(0);
+
+        if (instances.size() == 0)
+            throw new TestBug("There are no instances of class '" + className + "' in debuggee");
+
+        if (instances.size() > 1)
+            throw new TestBug("There are more than one(" + instances.size() + ") instance of '" + className + " in debuggee");
+
+        return instances.get(0);
+    }
+
+    protected BreakpointEvent waitForBreakpoint(BreakpointRequest breakpointRequest) {
+        BreakpointEvent breakpointEvent;
+
+        try {
+            breakpointEvent = (BreakpointEvent) debuggee.waitingEvent(breakpointRequest, argHandler.getWaitTime() * 60000);
+        } catch (InterruptedException e) {
+            setSuccess(false);
+            e.printStackTrace(log.getOutStream());
+            log.complain("unexpected InterruptedException: " + e);
+
+            breakpointEvent = null;
+        }
+
+        if (breakpointEvent == null) {
+            setSuccess(false);
+            log.complain("Didn't get expected breakpoint event");
+        }
+
+        return breakpointEvent;
+    }
+
+
+    private boolean currentSuccess = false;
+    protected void forceGC() {
+        pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_GC);
+        if (!isDebuggeeReady())
+            return;
+        currentSuccess = getSuccess();
+    }
+
+    // Get GC statistics
+    protected void resetStatusIfGC() {
+        pipe.println(AbstractDebuggeeTest.COMMAND_GC_COUNT);
+        String command = pipe.readln();
+        if (command.startsWith(AbstractDebuggeeTest.COMMAND_GC_COUNT)) {
+            if (!isDebuggeeReady()) {
+                return;
+            }
+            if (Integer.valueOf(command.substring(AbstractDebuggeeTest.COMMAND_GC_COUNT.length() + 1)) > 0) {
+                log.display("WARNING: The GC worked during tests. Results are skipped.");
+                setSuccess(currentSuccess);
+            }
+            return;
+        }
+        setSuccess(false);
+    }
+
+
+    protected BreakpointRequest defaultBreakpointRequest;
+
+    protected void initDefaultBreakpoint() {
+        defaultBreakpointRequest = debuggee.makeBreakpoint(debuggee.classByName(debuggeeClassNameWithoutArgs()),
+                AbstractDebuggeeTest.DEFAULT_BREAKPOINT_METHOD_NAME, AbstractDebuggeeTest.DEFAULT_BREAKPOINT_LINE);
+
+        defaultBreakpointRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
+        defaultBreakpointRequest.enable();
+    }
+
+    protected void removeDefaultBreakpoint() {
+        defaultBreakpointRequest.disable();
+        debuggee.getEventRequestManager().deleteEventRequest(defaultBreakpointRequest);
+        defaultBreakpointRequest = null;
+    }
+
+    protected Value createVoidValue() {
+        return vm.mirrorOfVoid();
+    }
+
+    // force debuggee call 'TestDebuggeeType2.breakpointMethod()'
+    protected BreakpointEvent forceBreakpoint() {
+        pipe.println(AbstractDebuggeeTest.COMMAND_FORCE_BREAKPOINT);
+
+        BreakpointEvent event = waitForBreakpoint(defaultBreakpointRequest);
+
+        return event;
+    }
+
+    protected void unexpectedException(Throwable t) {
+        setSuccess(false);
+        log.complain("Unexpected exception: " + t);
+        t.printStackTrace(log.getOutStream());
+    }
+
+    protected void display(String msg) {
+        log.display(msg);
+    }
+
+    protected void complain(String msg) {
+        log.complain("debugger FAILURE> " + msg + "\n");
+    }
+
+    protected boolean isJFR_active() {
+        return debuggee.isJFR_active();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/TestInterfaceImplementer1.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+interface Interface1 {
+
+}
+
+interface Interface2 {
+
+}
+
+interface Interface3 {
+
+}
+
+interface Interface4 {
+
+}
+
+interface Interface5 {
+
+}
+
+/*
+ * Empty class, used to be sure that there are no instances of this class in target VM
+ * Used in tests where interface implementer is needed
+ */
+public class TestInterfaceImplementer1 implements Interface1, Interface2, Interface3, Interface4, Interface5 {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ThreadState.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jdi;
+
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.TimeUnit;
+
+import nsk.share.Failure;
+
+/**
+ * Functions to set and wait for states in threads.
+ * Used to sync main thread and debuggee thread.
+ */
+public class ThreadState {
+    private final Lock lock = new ReentrantLock();
+    private final Condition cond = lock.newCondition();
+    private volatile String currentState;
+    private long timeoutMs;
+
+    public ThreadState(String startState, long timeoutMs) {
+        currentState = startState;
+        this.timeoutMs = timeoutMs;
+    }
+
+    /**
+     * Set new state.
+     */
+    public void setState(String newState) {
+        lock.lock();
+        try {
+            log(MSG_SET_STATE, newState);
+            currentState = newState;
+            cond.signalAll();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Wait for the specified state.
+     * Throws Failure if timeout.
+     */
+    public void waitForState(String waitState) {
+        lock.lock();
+        try {
+            log(MSG_WAIT_STATE, waitState);
+            while (!currentState.equals(waitState)) {
+                if (!cond.await(timeoutMs, TimeUnit.MILLISECONDS)) {
+                    throw new Failure(format(MSG_TIMEOUT, waitState));
+                }
+            }
+            log(MSG_GOT_STATE, waitState);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            throw new Failure(e);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Simple helper that sets a new state and then wait for another state.
+     */
+    public void setAndWait(String newState, String waitState) {
+        setState(newState);
+        waitForState(waitState);
+    }
+
+    private static final String MSG_TIMEOUT = "ThreadState(thread='%s', state='%s') timeout waiting for %s";
+    private static final String MSG_SET_STATE = "ThreadState(thread='%s', state='%s') set state to %s";
+    private static final String MSG_WAIT_STATE = "ThreadState(thread='%s', state='%s') waiting for state %s";
+    private static final String MSG_GOT_STATE = "ThreadState(thread='%s', state='%s') got state %s";
+
+    private String format(String pattern, String state) {
+        final String threadName = Thread.currentThread().getName();
+        return String.format(pattern, threadName, currentState, state);
+    }
+
+    private void log(String pattern, String state) {
+        System.out.println(format(pattern, state));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi;
+
+import java.lang.reflect.*;
+import nsk.share.*;
+import nsk.share.jpda.ConversionUtils;
+import com.sun.jdi.*;
+
+/*
+ * Class contains several common methods used by tests checking that values are
+ * correctly converted as a result of JDI interface work (e.g. when method
+ * 'ObjectReference.setValue(Field, Value)' is called)
+ */
+public class ValueConversionDebugger extends TestDebuggerType2 {
+
+    protected static enum ValueType {
+        BYTE,
+        CHAR,
+        SHORT,
+        INT,
+        LONG,
+        FLOAT,
+        DOUBLE
+    }
+
+    /*
+     * short aliases for ValueType members
+     */
+    protected static ValueType BYTE = ValueType.BYTE;
+    protected static ValueType CHAR = ValueType.CHAR;
+    protected static ValueType SHORT = ValueType.SHORT;
+    protected static ValueType INT = ValueType.INT;
+    protected static ValueType LONG = ValueType.LONG;
+    protected static ValueType FLOAT = ValueType.FLOAT;
+    protected static ValueType DOUBLE = ValueType.DOUBLE;
+
+    /*
+     * Is information lost when given PrimitiveValue converted to the
+     * primitive type representing by the destType
+     */
+    public static boolean informationLoss(PrimitiveValue value, Class destType) {
+        /*
+         * Use reflection here to avoid large nested switches
+         * (construct method name, method is located in the nsk.share.jpda.ConversionUtils)
+         */
+        String methodNameToCall = "informationLoss";
+
+        Object param = null;
+
+        if (value instanceof ByteValue) {
+            methodNameToCall += "ByteTo";
+            param = new Byte(value.byteValue());
+        } else if (value instanceof ShortValue) {
+            methodNameToCall += "ShortTo";
+            param = new Short(value.shortValue());
+        } else if (value instanceof CharValue) {
+            methodNameToCall += "CharTo";
+            param = new Character(value.charValue());
+        } else if (value instanceof IntegerValue) {
+            methodNameToCall += "IntTo";
+            param = new Integer(value.intValue());
+        } else if (value instanceof LongValue) {
+            methodNameToCall += "LongTo";
+            param = new Long(value.longValue());
+        } else if (value instanceof FloatValue) {
+            methodNameToCall += "FloatTo";
+            param = new Float(value.floatValue());
+        } else if (value instanceof DoubleValue) {
+            methodNameToCall += "DoubleTo";
+            param = new Double(value.doubleValue());
+        } else
+            throw new IllegalArgumentException("Illegal PrimitiveValue: " + value);
+
+        if (!destType.isPrimitive())
+            throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");
+
+        if (destType == Byte.TYPE) {
+            methodNameToCall += "Byte";
+        } else if (destType == Short.TYPE) {
+            methodNameToCall += "Short";
+        } else if (destType == Character.TYPE) {
+            methodNameToCall += "Char";
+        } else if (destType == Integer.TYPE) {
+            methodNameToCall += "Int";
+        } else if (destType == Long.TYPE) {
+            methodNameToCall += "Long";
+        } else if (destType == Float.TYPE) {
+            methodNameToCall += "Float";
+        } else if (destType == Double.TYPE) {
+            methodNameToCall += "Double";
+        } else
+            throw new IllegalArgumentException("Illegal destType: " + destType + ", should be primitive type");
+
+        java.lang.reflect.Method method;
+        try {
+            method = ConversionUtils.class.getMethod(methodNameToCall, param.getClass());
+        } catch (NoSuchMethodException e) {
+            throw new Failure("Unexpected exception: " + e, e);
+        }
+
+        try {
+            return (Boolean)method.invoke(null, new Object[]{param});
+        } catch (IllegalAccessException e) {
+            throw new Failure("Unexpected exception: " + e, e);
+        } catch (InvocationTargetException e) {
+            throw new Failure("Unexpected exception: " + e, e);
+        }
+    }
+
+    /*
+     * Is given PrimitiveValue can be converted to the primitive type represented by the
+     * destType without information loss
+     */
+    public static boolean isValidConversion(PrimitiveValue value, Class destType) {
+        return !informationLoss(value, destType);
+    }
+
+    /*
+     * Method is used in subclasses for creation of tested values
+     * (reflection is used to simplify coding)
+     */
+    protected PrimitiveValue createValue(Object arr, int arrayIndex) {
+        PrimitiveValue value;
+
+        if (arr instanceof byte[]) {
+            value = debuggee.VM().mirrorOf(Array.getByte(arr,arrayIndex));
+        } else if (arr instanceof char[]) {
+            value = debuggee.VM().mirrorOf(Array.getChar(arr,arrayIndex));
+        } else if (arr instanceof double[]) {
+            value = debuggee.VM().mirrorOf(Array.getDouble(arr,arrayIndex));
+        } else if (arr instanceof float[]) {
+            value = debuggee.VM().mirrorOf(Array.getFloat(arr,arrayIndex));
+        } else if (arr instanceof int[]) {
+            value = debuggee.VM().mirrorOf(Array.getInt(arr,arrayIndex));
+        } else if (arr instanceof long[]) {
+            value = debuggee.VM().mirrorOf(Array.getLong(arr,arrayIndex));
+        } else if (arr instanceof short[]) {
+            value = debuggee.VM().mirrorOf(Array.getShort(arr,arrayIndex));
+        } else {
+            setSuccess(false);
+            throw new TestBug("Unexpected object was passed in the 'createValue': " + arr);
+        }
+
+        return value;
+    }
+
+    /*
+     * used by subclasses for debug output
+     * (modified in the method 'isValidConversion')
+     */
+    protected String lastConversion;
+
+    /*
+     * Is given PrimitiveValue can be converted to the primitive type represented by the given type
+     * without information loss
+     */
+    protected boolean isValidConversion(ValueType type, PrimitiveValue value) {
+        com.sun.jdi.Type fromType = value.type();
+
+        boolean ret = false;
+        lastConversion = " conversion from "
+                            + value + "(" + fromType + ")" + " to ";
+        switch (type) {
+        case BYTE:
+                byte b = value.byteValue();
+                ret = isValidConversion(value, Byte.TYPE);
+                lastConversion += b + "(byte)";
+                break;
+        case CHAR:
+                char c = value.charValue();
+                ret = isValidConversion(value, Character.TYPE);
+                lastConversion += Integer.toHexString(c) + "(char)";
+                break;
+        case DOUBLE:
+                double d = value.doubleValue();
+                ret = isValidConversion(value, Double.TYPE);
+                lastConversion += d + "(double)";
+                break;
+        case FLOAT:
+                float f = value.floatValue();
+                ret = isValidConversion(value, Float.TYPE);
+                lastConversion += f + "(float)";
+                break;
+        case INT:
+                int i = value.intValue();
+                ret = isValidConversion(value, Integer.TYPE);
+                lastConversion += i + "(int)";
+                break;
+        case LONG:
+                long j = value.longValue();
+                ret = isValidConversion(value, Long.TYPE);
+                lastConversion += j + "(long)";
+                break;
+        case SHORT:
+                short s = value.shortValue();
+                ret = isValidConversion(value, Short.TYPE);
+                lastConversion += s + "(short)";
+                break;
+        default:
+            throw new IllegalArgumentException("Invalid type: " + type);
+        }
+        return ret;
+    }
+
+    /*
+     * Used in subclasses to check that given PrimitiveValue was correctly converted as a result
+     * of JDI interface work (retValue - conversion result)
+     * (
+     *  example:
+     *          test assigns DoubleValue = 1.5 (value) to the byte Field (retValue - ByteValue = 1),
+     *          in this case we should check that value.byteValue() == retValue.byteValue()
+     * )
+     */
+    protected void checkValueConversion(PrimitiveValue value, PrimitiveValue retValue) {
+        boolean res;
+
+        if (retValue instanceof ByteValue) {
+            res = value.byteValue() != retValue.byteValue();
+        } else if (retValue instanceof ShortValue) {
+            res = value.shortValue() != retValue.shortValue();
+        } else if (retValue instanceof CharValue) {
+            res = value.charValue() != retValue.charValue();
+        } else if (retValue instanceof IntegerValue) {
+            res = value.intValue() != retValue.intValue();
+        } else if (retValue instanceof LongValue) {
+            res = value.longValue() != retValue.longValue();
+        } else if (retValue instanceof FloatValue) {
+            res = value.floatValue() != retValue.floatValue();
+        } else if (retValue instanceof DoubleValue) {
+            res = value.doubleValue() != retValue.doubleValue();
+        } else {
+            throw new TestBug("Invalid value type in the 'checkValueConversion': " + retValue.type().name());
+        }
+
+        if (res) {
+            setSuccess(false);
+            complain("Conversion error");
+            complain("From type: " + value.type().name() + ", to type: " + retValue.type().name());
+            complain(retValue + " != " + value);
+            display("");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/InstallSDE.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi.sde;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+import nsk.share.Consts;
+
+/*
+ * Inserts in class file 'SourceDebugExtension' attribute based on input .SMAP file.
+ */
+public class InstallSDE {
+    static final String nameSDE = "SourceDebugExtension";
+
+    private byte[] orig;
+
+    private byte[] sdeAttr;
+
+    private byte[] gen;
+
+    private int origPos = 0;
+
+    private int genPos = 0;
+
+    private int sdeIndex;
+
+    public static void install(File inClassFile, File smapFile, File outClassFile, boolean verbose) throws IOException {
+        new InstallSDE(inClassFile, smapFile, outClassFile, verbose);
+    }
+
+    public static void install(byte[] aOrig, byte[] aSdeAttr, File outClassFile, boolean verbose) throws IOException {
+        new InstallSDE(aOrig, aSdeAttr, outClassFile, verbose);
+    }
+
+    public static void install(File inOutClassFile, File attrFile, boolean verbose) throws IOException {
+        File tmpFile = new File(inOutClassFile.getPath() + "tmp");
+
+        new InstallSDE(inOutClassFile, attrFile, tmpFile, verbose);
+
+        if (!inOutClassFile.delete()) {
+            throw new IOException("inOutClassFile.delete() failed");
+        }
+        if (!tmpFile.renameTo(inOutClassFile)) {
+            throw new IOException("tmpFile.renameTo(inOutClassFile) failed");
+        }
+    }
+
+    private static void abort(String msg) {
+        System.err.println(msg);
+        System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+    }
+
+    private InstallSDE(File inClassFile, File attrFile, File outClassFile, boolean verbose) throws IOException {
+        if (!inClassFile.exists()) {
+            abort("no such file: " + inClassFile);
+        }
+        if (!attrFile.exists()) {
+            abort("no such file: " + attrFile);
+        }
+
+        // get the bytes
+        orig = readWhole(inClassFile);
+        sdeAttr = readWhole(attrFile);
+        gen = new byte[orig.length + sdeAttr.length + 100];
+
+        // do it
+        addSDE(verbose);
+
+        // write result
+        FileOutputStream outStream = new FileOutputStream(outClassFile);
+        outStream.write(gen, 0, genPos);
+        outStream.close();
+    }
+
+    private InstallSDE(byte[] aOrig, byte[] aSdeAttr, File outClassFile, boolean verbose) throws IOException {
+        orig = aOrig;
+        sdeAttr = aSdeAttr;
+        gen = new byte[orig.length + sdeAttr.length + 100];
+
+        // do it
+        addSDE(verbose);
+
+        // write result
+        FileOutputStream outStream = new FileOutputStream(outClassFile);
+        outStream.write(gen, 0, genPos);
+        outStream.close();
+    }
+
+    private byte[] readWhole(File input) throws IOException {
+        FileInputStream inStream = new FileInputStream(input);
+        try {
+                return readWhole(inStream, (int) input.length());
+        } finally {
+                inStream.close();
+        }
+    }
+
+    private byte[] readWhole(InputStream inStream, int len) throws IOException {
+        byte[] bytes = new byte[len];
+
+        if (inStream.read(bytes, 0, len) != len) {
+            abort("expected size: " + len);
+        }
+
+        return bytes;
+    }
+
+    private void addSDE(boolean verbose) throws UnsupportedEncodingException {
+        copy(4 + 2 + 2); // magic min/maj version
+        int constantPoolCountPos = genPos;
+        int constantPoolCount = readU2();
+        writeU2(constantPoolCount);
+        // copy old constant pool return index of SDE symbol, if found
+        sdeIndex = copyConstantPool(constantPoolCount, verbose);
+        if (sdeIndex < 0) {
+            // if "SourceDebugExtension" symbol not there add it
+            writeUtf8ForSDE();
+
+            // increment the countantPoolCount
+            sdeIndex = constantPoolCount;
+            ++constantPoolCount;
+            randomAccessWriteU2(constantPoolCountPos, constantPoolCount);
+
+            if (verbose) {
+                System.out.println("SourceDebugExtension not found, installed at: " + sdeIndex);
+            }
+        } else {
+            if (verbose) {
+                System.out.println("SourceDebugExtension found at: " + sdeIndex);
+            }
+        }
+        copy(2 + 2 + 2); // access, this, super
+        int interfaceCount = readU2();
+        writeU2(interfaceCount);
+        if (verbose) {
+            System.out.println("interfaceCount: " + interfaceCount);
+        }
+        copy(interfaceCount * 2);
+        copyMembers(verbose); // fields
+        copyMembers(verbose); // methods
+        int attrCountPos = genPos;
+        int attrCount = readU2();
+        writeU2(attrCount);
+        if (verbose) {
+            System.out.println("class attrCount: " + attrCount);
+        }
+        // copy the class attributes, return true if SDE attr found (not copied)
+        if (!copyAttrs(attrCount, verbose)) {
+            // we will be adding SDE and it isn't already counted
+            ++attrCount;
+            randomAccessWriteU2(attrCountPos, attrCount);
+            if (verbose) {
+                System.out.println("class attrCount incremented");
+            }
+        }
+        writeAttrForSDE(sdeIndex);
+    }
+
+    private void copyMembers(boolean verbose) {
+        int count = readU2();
+        writeU2(count);
+        if (verbose) {
+            System.out.println("members count: " + count);
+        }
+        for (int i = 0; i < count; ++i) {
+            copy(6); // access, name, descriptor
+            int attrCount = readU2();
+            writeU2(attrCount);
+            if (verbose) {
+                System.out.println("member attr count: " + attrCount);
+            }
+            copyAttrs(attrCount, verbose);
+        }
+    }
+
+    private boolean copyAttrs(int attrCount, boolean verbose) {
+        boolean sdeFound = false;
+        for (int i = 0; i < attrCount; ++i) {
+            int nameIndex = readU2();
+            // don't write old SDE
+            if (nameIndex == sdeIndex) {
+                sdeFound = true;
+                if (verbose) {
+                    System.out.println("SDE attr found");
+                }
+            } else {
+                writeU2(nameIndex); // name
+                int len = readU4();
+                writeU4(len);
+                copy(len);
+                if (verbose) {
+                    System.out.println("attr len: " + len);
+                }
+            }
+        }
+        return sdeFound;
+    }
+
+    private void writeAttrForSDE(int index) {
+        writeU2(index);
+        writeU4(sdeAttr.length);
+        for (int i = 0; i < sdeAttr.length; ++i) {
+            writeU1(sdeAttr[i]);
+        }
+    }
+
+    private void randomAccessWriteU2(int pos, int val) {
+        int savePos = genPos;
+        genPos = pos;
+        writeU2(val);
+        genPos = savePos;
+    }
+
+    private int readU1() {
+        return ((int) orig[origPos++]) & 0xFF;
+    }
+
+    private int readU2() {
+        int res = readU1();
+        return (res << 8) + readU1();
+    }
+
+    private int readU4() {
+        int res = readU2();
+        return (res << 16) + readU2();
+    }
+
+    private void writeU1(int val) {
+        gen[genPos++] = (byte) val;
+    }
+
+    private void writeU2(int val) {
+        writeU1(val >> 8);
+        writeU1(val & 0xFF);
+    }
+
+    private void writeU4(int val) {
+        writeU2(val >> 16);
+        writeU2(val & 0xFFFF);
+    }
+
+    private void copy(int count) {
+        for (int i = 0; i < count; ++i) {
+            gen[genPos++] = orig[origPos++];
+        }
+    }
+
+    private byte[] readBytes(int count) {
+        byte[] bytes = new byte[count];
+        for (int i = 0; i < count; ++i) {
+            bytes[i] = orig[origPos++];
+        }
+        return bytes;
+    }
+
+    private void writeBytes(byte[] bytes) {
+        for (int i = 0; i < bytes.length; ++i) {
+            gen[genPos++] = bytes[i];
+        }
+    }
+
+    private int copyConstantPool(int constantPoolCount, boolean verbose) throws UnsupportedEncodingException {
+        int sdeIndex = -1;
+        // copy const pool index zero not in class file
+        if ( verbose )
+                System.out.println("cp count=" + constantPoolCount);
+        for (int i = 1; i < constantPoolCount; ++i) {
+            int tag = readU1();
+            writeU1(tag);
+            if ( verbose )
+                System.out.println(i + ": tag=" + tag);
+            switch (tag) {
+            case 7: // Class
+            case 8: // String
+            case 16: // MethodType
+                copy(2);
+                break;
+            case 15: // MethodHandle
+                copy(3);
+                break;
+            case 9: // Field
+            case 10: // Method
+            case 11: // InterfaceMethod
+            case 3: // Integer
+            case 4: // Float
+            case 12: // NameAndType
+            case 17: // InvokeDynamic_17 (will go away)
+            case 18: // InokeDynamic
+                copy(4);
+                break;
+            case 5: // Long
+            case 6: // Double
+                copy(8);
+                ++i;
+                break;
+            case 1: // Utf8
+                int len = readU2();
+                writeU2(len);
+                byte[] utf8 = readBytes(len);
+                String str = new String(utf8, "UTF-8");
+                if (verbose) {
+                    System.out.println(i + " read class attr -- '" + str + "'");
+                }
+                if (str.equals(nameSDE)) {
+                    sdeIndex = i;
+                }
+                writeBytes(utf8);
+                break;
+            default:
+                abort("unexpected tag: " + tag);
+                break;
+            }
+        }
+        return sdeIndex;
+    }
+
+    private void writeUtf8ForSDE() {
+        int len = nameSDE.length();
+        writeU1(1); // Utf8 tag
+        writeU2(len);
+        for (int i = 0; i < len; ++i) {
+            writeU1(nameSDE.charAt(i));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SDEDebuggee.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi.sde;
+
+import java.lang.reflect.Method;
+import nsk.share.TestBug;
+import nsk.share.jdi.*;
+
+public class SDEDebuggee extends AbstractJDIDebuggee {
+    public static String mainThreadName = "SDEDebuggee_mainThread";
+
+    // command:class_name
+    public static String COMMAND_EXECUTE_TEST_METHODS = "executeTestMethods";
+
+    public static void main(String args[]) {
+        new SDEDebuggee().doTest(args);
+    }
+
+    protected String[] doInit(String[] args) {
+        args = super.doInit(args);
+
+        if (classpath == null)
+            throw new TestBug("Debuggee requires '-testClassPath' parameter");
+
+        Thread.currentThread().setName(mainThreadName);
+
+        return args;
+    }
+
+    public boolean parseCommand(String command) {
+        if (super.parseCommand(command))
+            return true;
+
+        if (command.startsWith(COMMAND_EXECUTE_TEST_METHODS)) {
+            // extract class name
+            String split[] = command.split(":");
+
+            if ((split.length != 2) || (split[1].length() == 0))
+                throw new TestBug("");
+
+            executeTestMethods(split[1]);
+            breakpointMethod();
+
+            return true;
+        }
+
+        return false;
+    }
+
+    // create instance of given class and execute all methods which names start
+    // with 'sde_testMethod'
+    private void executeTestMethods(String className) {
+        TestClassLoader classLoader = new TestClassLoader();
+        classLoader.setClassPath(classpath);
+
+        try {
+            Class<?> klass = classLoader.loadClass(className);
+            Object testObject = klass.newInstance();
+
+            for (Method method : klass.getDeclaredMethods()) {
+                if (method.getName().startsWith("sde_testMethod"))
+                    method.invoke(testObject, new Object[] {});
+            }
+        } catch (Exception e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+
+            throw new TestBug("Unexpected exception: " + e);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SDEDebugger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,1123 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi.sde;
+
+import java.io.*;
+import java.nio.channels.FileChannel;
+import java.util.*;
+import com.sun.jdi.*;
+import com.sun.jdi.event.BreakpointEvent;
+import com.sun.jdi.event.Event;
+import com.sun.jdi.event.StepEvent;
+import nsk.share.ClassFileFinder;
+import nsk.share.TestBug;
+import nsk.share.jdi.EventHandler;
+import nsk.share.jdi.TestDebuggerType2;
+
+/*
+ * Class is used as base debugger for SDE tests.
+ *
+ * This class contains several methods called 'prepareDefaultPatchedClassFile_TypeXXX' which create
+ * class file with added SourceDebugExtension attribute and return debug information about created file.
+ * (this methods was moved in SDEDebugger class if similar generated class files were used in 2 or more tests)
+ *
+ *
+ */
+public class SDEDebugger extends TestDebuggerType2 {
+    protected static final int INIT_LINE = 32;    // n.s.j.sde.TestClass1::<init>
+    protected static final int METHOD1_LINE = 43; // n.s.j.sde.TestClass1::sde_testMethod1
+    protected static final int METHOD2_LINE = 54; // n.s.j.sde.TestClass1::sde_testMethod2
+    public static String javaStratumName = "Java";
+
+    // Set debug data for "Java" stratum for TestClass1
+    public static List<DebugLocation> javaStratumLocations_TestClass1 = new ArrayList<DebugLocation>();
+
+    public static String javaSourceName_TestClass1 = "TestClass1.java";
+
+    public static String javaSourcePath_TestClass1 = "nsk" + File.separator + "share" + File.separator + "jdi"
+            + File.separator + "sde" + File.separator + "TestClass1.java";
+
+    static {
+        for (int i = 0; i < 8; i++) {
+            javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
+                    "<init>", INIT_LINE + i, INIT_LINE + i));
+            javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
+                    "sde_testMethod1", METHOD1_LINE + i, METHOD1_LINE + i));
+            javaStratumLocations_TestClass1.add(new DebugLocation(javaSourceName_TestClass1, javaSourcePath_TestClass1,
+                    "sde_testMethod2", METHOD2_LINE + i, METHOD2_LINE + i));
+        }
+    }
+
+    // insert debug information about "Java" stratum in the given Map<String,
+    // LocationsData>
+    static protected void addJavaLocations(Map<String, LocationsData> testStratumData, boolean setJavaStratumDefault) {
+        LocationsData locationsData = new LocationsData(javaStratumName);
+
+        if (setJavaStratumDefault)
+            locationsData.isDefault = true;
+
+        locationsData.paths.add(javaSourcePath_TestClass1);
+        locationsData.allLocations.addAll(javaStratumLocations_TestClass1);
+        locationsData.sourceLocations.put(javaSourceName_TestClass1, javaStratumLocations_TestClass1);
+
+        testStratumData.put(javaStratumName, locationsData);
+
+    }
+
+    // common base names for test stratum, stratum source name and stratum
+    // source path
+    public static final String testStratumName = "TestStratum";
+
+    public static final String testStratumSourceName = "testSource";
+
+    public static final String testStratumSourcePath = "testSourcePath";
+
+    // Event listener thread which saves all received StepEvents
+    public class StepEventListener extends EventHandler.EventListener {
+        // is BreakpointEvent was received (debuggee should stop at breakpoint
+        // after StepEvents generation)
+        private volatile boolean breakpointEventReceived;
+
+        private List<Location> stepLocations = new ArrayList<Location>();
+
+        public List<Location> stepLocations() {
+            return stepLocations;
+        }
+
+        public void clearLocations() {
+            stepLocations.clear();
+        }
+
+        public boolean eventReceived(Event event) {
+            if (event instanceof StepEvent) {
+                StepEvent stepEvent = (StepEvent) event;
+
+                stepLocations.add(stepEvent.location());
+
+                vm.resume();
+
+                return true;
+            }
+            // debuggee should stop after event generation
+            else if (event instanceof BreakpointEvent) {
+                breakpointEventReceived = true;
+                vm.resume();
+
+                return true;
+            }
+
+            return false;
+        }
+
+        public void waitBreakpointEvent() {
+            while (!breakpointEventReceived)
+                Thread.yield();
+        }
+    }
+
+    // debug information about location (implements Comparable to make possible
+    // using DebugLocation with java.util.Set)
+    public static class DebugLocation implements Comparable<DebugLocation> {
+        public DebugLocation(String sourceName, String sourcePath, String methodName, int inputLine, int outputLine) {
+            this.sourceName = sourceName;
+            this.sourcePath = sourcePath;
+            this.inputLine = inputLine;
+            this.outputLine = outputLine;
+            this.methodName = methodName;
+        }
+
+        public String sourceName;
+
+        public String sourcePath;
+
+        public String methodName;
+
+        public int inputLine;
+
+        public int outputLine;
+
+        public String toString() {
+            return "Line number: " + inputLine + " SourceName: " + sourceName + " SourcePath: " + sourcePath;
+        }
+
+        // compare DebugLocation with com.sun.jdi.Location
+        public boolean compare(Location location, String stratum) {
+            try {
+                if (stratum == null) {
+                    return (location.lineNumber() == inputLine) && location.sourceName().equals(sourceName)
+                            && location.sourcePath().equals(sourcePath);
+                } else {
+                    return (location.lineNumber(stratum) == inputLine)
+                            && location.sourceName(stratum).equals(sourceName)
+                            && location.sourcePath(stratum).equals(sourcePath);
+                }
+            } catch (AbsentInformationException e) {
+                return false;
+            }
+        }
+
+        // used to find locations for given line
+        public boolean isConform(String sourceName, int lineNumber) {
+            boolean sourceConform = (sourceName == null ? true : this.sourceName.equals(sourceName));
+
+            return sourceConform && (this.inputLine == lineNumber);
+        }
+
+        // implements this method to make possible using DebugLocation with java.util.Set
+        public int compareTo(DebugLocation location) {
+            return (this.sourceName.equals(location.sourceName) && this.inputLine == location.inputLine) ? 0 : 1;
+        }
+    }
+
+    // Class contains debug information about sources, paths, locations
+    // available for class
+    public static class LocationsData {
+        public LocationsData(String stratumName) {
+            this.stratumName = stratumName;
+        }
+
+        public List<String> sourceNames() {
+            List<String> sourceNames = new ArrayList<String>();
+            sourceNames.addAll(sourceLocations.keySet());
+
+            return sourceNames;
+        }
+
+        public String stratumName;
+
+        // is stratum default for ReferenceType
+        public boolean isDefault;
+
+        // locations for source files
+        public Map<String, List<DebugLocation>> sourceLocations = new TreeMap<String, List<DebugLocation>>();
+
+        // all locations for stratum
+        public List<DebugLocation> allLocations = new ArrayList<DebugLocation>();
+
+        // all paths for stratum
+        public List<String> paths = new ArrayList<String>();
+    }
+
+    static protected String locationToString(Location location, String stratum) {
+        String result;
+
+        result = "Line number: " + (stratum == null ? location.lineNumber() : location.lineNumber(stratum));
+
+        try {
+            result += (" Source name: " + (stratum == null ? location.sourceName() : location.sourceName(stratum)));
+        } catch (AbsentInformationException e) {
+            result += (" Source name: " + " INFORMATION IS ABSENT");
+        }
+
+        try {
+            result += (" Source path: " + (stratum == null ? location.sourcePath() : location.sourcePath(stratum)));
+        } catch (AbsentInformationException e) {
+            result += (" Source path: " + " INFORMATION IS ABSENT");
+        }
+
+        return result;
+    }
+
+    // seach class file for given class and create copy of this class file in
+    // 'testWorkDir' directory
+    protected File createLocalClassfileCopy(String className) throws IOException {
+        int index = className.lastIndexOf(".");
+
+        String path;
+
+        if (index < 0)
+            path = "";
+        else
+            path = className.substring(0, index).replace(".", "/");
+
+        File dirs = new File(testWorkDir + "/" + path);
+        dirs.mkdirs();
+
+        File oldFile = null;
+        {
+            java.nio.file.Path tmp = ClassFileFinder.findClassFile(className, classpath);
+            oldFile = tmp == null ? null : tmp.toFile();
+        }
+        File newFile = copyFile(oldFile,
+                testWorkDir + "/" + className.replace(".", "/") + ".class");
+
+        return newFile;
+    }
+
+    // create class file with multiple strata
+    protected void savePathcedClassFile(String className, SmapGenerator smapGenerator, String smapFileName) {
+        File patchedClassFile = null;
+
+        try {
+            patchedClassFile = createLocalClassfileCopy(className);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Unexpected IO exception: " + e);
+        }
+
+        smapFileName = testWorkDir + "/" + smapFileName;
+        smapGenerator.setOutputFileName(smapFileName);
+
+        File smapFile = null;
+
+        try {
+            smapFile = smapGenerator.saveToFile(smapFileName);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Unexpected IO exception: " + e);
+        }
+
+        log.display("Add for class " + className + " following SDE: ");
+        log.display(smapGenerator.getString());
+
+        try {
+            InstallSDE.install(patchedClassFile, smapFile, false);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Unexpected IO exception: " + e);
+        }
+    }
+
+    // common for SDE tests debuggee name
+    protected String debuggeeClassName() {
+        if (classpath == null) {
+            throw new TestBug("Debugger requires 'testClassPath' parameter");
+        }
+
+        return SDEDebuggee.class.getName() + " -testClassPath " + testWorkDir;
+    }
+
+    // parses common for all SDE - tests parameters
+    protected String[] doInit(String args[], PrintStream out) {
+        args = super.doInit(args, out);
+
+        if (classpath == null) {
+            throw new TestBug("Debugger requires 'testClassPath' parameter");
+        }
+        if (testWorkDir == null) {
+            throw new TestBug("Debugger requires 'testWorkDir' parameter");
+        }
+
+        return args;
+    }
+
+    // single input line is mapped to the single output line, test stratum has
+    // single source
+    protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type1(String className, int testStratumCount,
+            boolean setJavaStratumDefault) {
+        /*
+         * "Java" "TestStratum"
+         *
+         * <init>
+         * 32 --> 1000, source1
+         * 33 --> 1001, source1
+         * ...
+         * ...
+         * 39 --> 1007, source1
+         *
+         * sde_testMethod1
+         *
+         * 43 --> 1100, source1
+         * 44 --> 1101, source1
+         * ...
+         * ...
+         * 50 --> 1107, source1
+         *
+         * sde_testMethod1
+         * 54 --> 1200, source1
+         * 55 --> 1201, source1
+         * ...
+         * ...
+         * 61 --> 1207, source1
+         */
+
+        Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
+
+        String smapFileName = "TestSMAP.smap";
+        SmapGenerator smapGenerator = new SmapGenerator();
+
+        for (int i = 0; i < testStratumCount; i++) {
+            String stratumName = testStratumName + (i + 1);
+
+            LocationsData locationsData = new LocationsData(stratumName);
+
+            String sourceName = testStratumSourceName + (i + 1);
+            String sourcePath = testStratumSourcePath + (i + 1);
+
+            locationsData.paths.add(sourcePath);
+
+            SmapStratum smapStratum = new SmapStratum(stratumName);
+
+            List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
+
+            int baseLineNumber = 1000 * (i + 1);
+
+            for (int j = 0; j < 8; j++) {
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "<init>", baseLineNumber + j, INIT_LINE + j));
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "sde_testMethod1", baseLineNumber + 100 + j, METHOD1_LINE + j));
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "sde_testMethod2", baseLineNumber + 200 + j, METHOD2_LINE + j));
+            }
+
+            locationsData.sourceLocations.put(sourceName, sourceLocations);
+            locationsData.allLocations.addAll(sourceLocations);
+
+            testStratumData.put(stratumName, locationsData);
+
+            smapStratum.addFile(sourceName, sourcePath);
+
+            for (DebugLocation debugLocation : sourceLocations) {
+                smapStratum.addLineData(debugLocation.inputLine, sourceName, 1, debugLocation.outputLine, 1);
+            }
+
+            // if setJavaStratumDefault == false do first test stratum default
+            if (!(setJavaStratumDefault) && (i == 0)) {
+                locationsData.isDefault = true;
+                smapGenerator.addStratum(smapStratum, true);
+            } else
+                smapGenerator.addStratum(smapStratum, false);
+        }
+
+        savePathcedClassFile(className, smapGenerator, smapFileName);
+
+        addJavaLocations(testStratumData, setJavaStratumDefault);
+
+        return testStratumData;
+    }
+
+    // single input line is mapped to the single output line, test stratum has 3
+    // sources
+    protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type2(String className, int testStratumCount) {
+        /*
+         * "Java" "TestStratum"
+         *
+         * <init>
+         * 32 --> 1000, source1, path1
+         * 33 --> 1001, source2, path2
+         * 34 --> 1002, source3, path3
+         * ...
+         * ...
+         *
+         * sde_testMethod1
+         * 43 --> 1100, source1, path1
+         * 44 --> 1101, source2, path2
+         * 45 --> 1102, source3, path3
+         * ...
+         * ...
+         *
+         * sde_testMethod2
+         * 54 --> 1200, source1, path1
+         * 55 --> 1201, source2, path2
+         * 56 --> 1207, source3, path3
+         * ...
+         * ...
+         */
+
+        Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
+
+        String smapFileName = "TestSMAP.smap";
+        SmapGenerator smapGenerator = new SmapGenerator();
+
+        for (int i = 0; i < testStratumCount; i++) {
+            String stratumName = testStratumName + (i + 1);
+            SmapStratum smapStratum = new SmapStratum(stratumName);
+
+            LocationsData locationsData = new LocationsData(stratumName);
+
+            String sourceName1 = testStratumSourceName + (i + 1) + "_1";
+            String sourcePath1 = testStratumSourcePath + (i + 1) + "_1";
+            locationsData.paths.add(sourcePath1);
+            smapStratum.addFile(sourceName1, sourcePath1);
+
+            String sourceName2 = testStratumSourceName + (i + 1) + "_2";
+            String sourcePath2 = testStratumSourcePath + (i + 1) + "_2";
+            locationsData.paths.add(sourcePath2);
+            smapStratum.addFile(sourceName2, sourcePath2);
+
+            String sourceName3 = testStratumSourceName + (i + 1) + "_3";
+            String sourcePath3 = testStratumSourcePath + (i + 1) + "_3";
+            locationsData.paths.add(sourcePath3);
+            smapStratum.addFile(sourceName3, sourcePath3);
+
+            List<DebugLocation> source1Locations = new ArrayList<DebugLocation>();
+            List<DebugLocation> source2Locations = new ArrayList<DebugLocation>();
+            List<DebugLocation> source3Locations = new ArrayList<DebugLocation>();
+
+            for (int j = 0; j < 8; j++) {
+                if (j % 3 == 0) {
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "<init>", 1000 + j, INIT_LINE + j));
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
+                } else if (j % 3 == 1) {
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "<init>", 1000 + j, INIT_LINE + j));
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
+                } else {
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "<init>", 1000 + j, INIT_LINE + j));
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "sde_testMethod1", 1101 + j, METHOD1_LINE + j));
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "sde_testMethod2", 1201 + j, METHOD2_LINE + j));
+                }
+            }
+
+            locationsData.sourceLocations.put(sourceName1, source1Locations);
+            locationsData.sourceLocations.put(sourceName2, source2Locations);
+            locationsData.sourceLocations.put(sourceName3, source3Locations);
+
+            locationsData.allLocations.addAll(source1Locations);
+            locationsData.allLocations.addAll(source2Locations);
+            locationsData.allLocations.addAll(source3Locations);
+
+            for (DebugLocation debugLocation : locationsData.allLocations) {
+                smapStratum.addLineData(
+                        debugLocation.inputLine,
+                        debugLocation.sourceName,
+                        1,
+                        debugLocation.outputLine,
+                        1);
+            }
+
+            smapGenerator.addStratum(smapStratum, false);
+
+            testStratumData.put(stratumName, locationsData);
+        }
+
+        savePathcedClassFile(className, smapGenerator, smapFileName);
+
+        addJavaLocations(testStratumData, true);
+
+        return testStratumData;
+    }
+
+    // single input line is mapped to two output lines
+    protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type3(String className, int testStratumCount,
+            boolean setJavaStratumDefault) {
+        /*
+         * "Java" "TestStratum"
+         *
+         * <init>
+         * 32 --> 1001, source1
+         * 34 --> 1002, source1
+         * 36 --> 1003, source1
+         * 38 --> 1004, source1
+         *
+         * sde_testMethod1
+         * 43 --> 1101, source1
+         * 45 --> 1102, source1
+         * 47 --> 1103, source1
+         * 49 --> 1104, source1
+         *
+         * sde_testMethod2
+         * 54 --> 1201, source1
+         * 56 --> 1202, source1
+         * 58 --> 1203, source1
+         * 60 --> 1204, source1
+         */
+
+        Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
+
+        String smapFileName = "TestSMAP.smap";
+        SmapGenerator smapGenerator = new SmapGenerator();
+
+        for (int i = 0; i < testStratumCount; i++) {
+            String stratumName = testStratumName + (i + 1);
+            LocationsData locationsData = new LocationsData(stratumName);
+
+            String sourceName = testStratumSourceName + (i + 1);
+            String sourcePath = testStratumSourcePath + (i + 1);
+            locationsData.paths.add(sourcePath);
+
+            SmapStratum smapStratum = new SmapStratum(stratumName);
+
+            List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
+
+            int baseLineNumber = 1000 * (i + 1);
+
+            for (int j = 0; j < 4; j++) {
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "<init>", baseLineNumber + j, INIT_LINE + j * 2));
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "sde_testMethod1", baseLineNumber + 100 + j, METHOD1_LINE + j * 2));
+                sourceLocations.add(new DebugLocation(sourceName, sourcePath,
+                        "sde_testMethod2", baseLineNumber + 200 + j, METHOD2_LINE + j * 2));
+            }
+
+            locationsData.allLocations.addAll(sourceLocations);
+            locationsData.sourceLocations.put(sourceName, sourceLocations);
+
+            testStratumData.put(stratumName, locationsData);
+
+            smapStratum.addFile(sourceName, sourcePath);
+
+            for (DebugLocation debugLocation : locationsData.allLocations) {
+                smapStratum.addLineData(debugLocation.inputLine, sourceName, 1, debugLocation.outputLine, 1);
+            }
+
+            // if setJavaStratumDefault == false do first stratum default
+            if (!setJavaStratumDefault && (i == 0)) {
+                locationsData.isDefault = true;
+                smapGenerator.addStratum(smapStratum, true);
+            } else
+                smapGenerator.addStratum(smapStratum, false);
+        }
+
+        savePathcedClassFile(className, smapGenerator, smapFileName);
+
+        addJavaLocations(testStratumData, setJavaStratumDefault);
+
+        return testStratumData;
+    }
+
+    // 3 different test stratums define disjoint locations sets
+    protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type4(String className) {
+        /*
+         * "Java" "TestStratum1" "TestStratum2" "TestStratum3"
+         *
+         * <init>
+         * 32 --> 1000
+         * ...
+         * ...
+         * 39 --> 1007
+         *
+         * sde_testMethod1
+         * 43 --> 1100
+         * ...
+         * ...
+         * 50 --> 1107
+         *
+         * sde_testMethod2
+         * 54 --> 1200
+         * ...
+         * ...
+         * 61 --> 1207
+         */
+        Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
+
+        String smapFileName = "TestSMAP.smap";
+
+        SmapGenerator smapGenerator = new SmapGenerator();
+
+        String stratumName = testStratumName + "1";
+        LocationsData locationsData = new LocationsData(stratumName);
+        List<DebugLocation> sourceLocations = new ArrayList<DebugLocation>();
+        String methodName = "<init>";
+        for (int i = 0; i < 8; i++) {
+            sourceLocations.add(new DebugLocation(
+                    testStratumSourceName, testStratumSourcePath, methodName,
+                    1000 + i, INIT_LINE + i));
+        }
+        locationsData.allLocations.addAll(sourceLocations);
+        locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
+        testStratumData.put(stratumName, locationsData);
+
+        stratumName = testStratumName + "2";
+        locationsData = new LocationsData(stratumName);
+        sourceLocations = new ArrayList<DebugLocation>();
+        methodName = "sde_testMethod1";
+        for (int i = 0; i < 8; i++) {
+            sourceLocations.add(new DebugLocation(
+                    testStratumSourceName, testStratumSourcePath, methodName,
+                    1100 + i, METHOD1_LINE + i));
+        }
+        locationsData.allLocations.addAll(sourceLocations);
+        locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
+        testStratumData.put(stratumName, locationsData);
+
+        stratumName = testStratumName + "3";
+        locationsData = new LocationsData(stratumName);
+        sourceLocations = new ArrayList<DebugLocation>();
+        methodName = "sde_testMethod2";
+        for (int i = 0; i < 8; i++) {
+            sourceLocations.add(new DebugLocation(testStratumSourceName, testStratumSourcePath,
+                    methodName, 1200 + i, METHOD2_LINE + i));
+        }
+        locationsData.allLocations.addAll(sourceLocations);
+        locationsData.sourceLocations.put(testStratumSourceName, sourceLocations);
+        testStratumData.put(stratumName, locationsData);
+
+        for (String stratum : testStratumData.keySet()) {
+            SmapStratum smapStratum = new SmapStratum(stratum);
+            smapStratum.addFile(testStratumSourceName, testStratumSourcePath);
+
+            for (DebugLocation debugLocation : testStratumData.get(stratum).allLocations)
+                smapStratum.addLineData(
+                        debugLocation.inputLine,
+                        debugLocation.sourceName,
+                        1,
+                        debugLocation.outputLine,
+                        1);
+
+            smapGenerator.addStratum(smapStratum, false);
+        }
+
+        savePathcedClassFile(className, smapGenerator, smapFileName);
+
+        return testStratumData;
+    }
+
+    // single input line is mapped to the single output line, test stratum has 3
+    // sources,
+    // lines in each method has same numbers, each method has locations in 3
+    // sources
+    protected Map<String, LocationsData> prepareDefaultPatchedClassFile_Type5(String className, int testStratumCount) {
+        /*
+         * "Java" "TestStratum"
+         *
+         * <init>
+         * 32 --> 1000, source1, path1
+         * 33 --> 1000, source2, path2
+         * 34 --> 1000, source3, path3
+         * ...
+         * ...
+         *
+         * sde_testMethod1
+         * 43 --> 1100, source1, path1
+         * 44 --> 1100, source2, path2
+         * 45 --> 1100, source3, path3
+         * ...
+         * ...
+         *
+         * sde_testMethod2
+         * 54 --> 1200, source1, path1
+         * 55 --> 1200, source2, path2
+         * 56 --> 1200, source3, path3
+         * ...
+         * ...
+         */
+
+        Map<String, LocationsData> testStratumData = new TreeMap<String, LocationsData>();
+
+        String smapFileName = "TestSMAP.smap";
+        SmapGenerator smapGenerator = new SmapGenerator();
+
+        for (int i = 0; i < testStratumCount; i++) {
+            String stratumName = testStratumName + (i + 1);
+            SmapStratum smapStratum = new SmapStratum(stratumName);
+
+            LocationsData locationsData = new LocationsData(stratumName);
+
+            String sourceName1 = testStratumSourceName + (i + 1) + "_1";
+            String sourcePath1 = testStratumSourcePath + (i + 1) + "_1";
+            locationsData.paths.add(sourcePath1);
+            smapStratum.addFile(sourceName1, sourcePath1);
+
+            String sourceName2 = testStratumSourceName + (i + 1) + "_2";
+            String sourcePath2 = testStratumSourcePath + (i + 1) + "_2";
+            locationsData.paths.add(sourcePath2);
+            smapStratum.addFile(sourceName2, sourcePath2);
+
+            String sourceName3 = testStratumSourceName + (i + 1) + "_3";
+            String sourcePath3 = testStratumSourcePath + (i + 1) + "_3";
+            locationsData.paths.add(sourcePath3);
+            smapStratum.addFile(sourceName3, sourcePath3);
+
+            List<DebugLocation> source1Locations = new ArrayList<DebugLocation>();
+            List<DebugLocation> source2Locations = new ArrayList<DebugLocation>();
+            List<DebugLocation> source3Locations = new ArrayList<DebugLocation>();
+
+            for (int j = 0; j < 8; j++) {
+                if (j % 3 == 0) {
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "<init>", 1000, INIT_LINE + j));
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "sde_testMethod1", 1100, METHOD1_LINE + j));
+                    source1Locations.add(new DebugLocation(sourceName1, sourcePath1,
+                            "sde_testMethod2", 1200, METHOD2_LINE + j));
+                } else if (j % 3 == 1) {
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "<init>", 1000, INIT_LINE + j));
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "sde_testMethod1", 1100, METHOD1_LINE + j));
+                    source2Locations.add(new DebugLocation(sourceName2, sourcePath2,
+                            "sde_testMethod2", 1200, METHOD2_LINE + j));
+                } else {
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "<init>", 1000, INIT_LINE + j));
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "sde_testMethod1", 1100, METHOD1_LINE + j));
+                    source3Locations.add(new DebugLocation(sourceName3, sourcePath3,
+                            "sde_testMethod2", 1200, METHOD2_LINE + j));
+                }
+            }
+
+            locationsData.sourceLocations.put(sourceName1, source1Locations);
+            locationsData.sourceLocations.put(sourceName2, source2Locations);
+            locationsData.sourceLocations.put(sourceName3, source3Locations);
+
+            locationsData.allLocations.addAll(source1Locations);
+            locationsData.allLocations.addAll(source2Locations);
+            locationsData.allLocations.addAll(source3Locations);
+
+            for (DebugLocation debugLocation : locationsData.allLocations) {
+                smapStratum.addLineData(
+                        debugLocation.inputLine,
+                        debugLocation.sourceName,
+                        1,
+                        debugLocation.outputLine,
+                        1);
+            }
+
+            smapGenerator.addStratum(smapStratum, false);
+
+            testStratumData.put(stratumName, locationsData);
+        }
+
+        savePathcedClassFile(className, smapGenerator, smapFileName);
+
+        return testStratumData;
+    }
+
+    public static File copyFile(File srcFile, String newFileName) throws IOException {
+        FileChannel inChannel = new FileInputStream(srcFile).getChannel();
+
+        File newFile = new File(newFileName);
+        newFile.createNewFile();
+        FileChannel outChannel = new FileOutputStream(newFile).getChannel();
+
+        outChannel.transferFrom(inChannel, 0, inChannel.size());
+
+        outChannel.close();
+        inChannel.close();
+
+        return newFile;
+    }
+
+    // find all locations of method with given name
+    // (used to check result of 'Method.allLineLocations()')
+    static protected List<DebugLocation> locationsOfMethod(List<DebugLocation> debugLocations, String methodName) {
+        List<DebugLocation> result = new ArrayList<DebugLocation>();
+
+        for (DebugLocation debugLocation : debugLocations) {
+            if (debugLocation.methodName.equals(methodName))
+                result.add(debugLocation);
+        }
+
+        return result;
+    }
+
+    // find all locations for given line and source name
+    // (used to check result of 'Method.locationsOfLine()' and
+    // 'ReferenceType.locationsOfLine()')
+    static protected List<DebugLocation> locationsOfLine(List<DebugLocation> debugLocations, String sourceName,
+            int lineNumber) {
+        List<DebugLocation> result = new ArrayList<DebugLocation>();
+
+        for (DebugLocation debugLocation : debugLocations) {
+            if (debugLocation.isConform(sourceName, lineNumber))
+                result.add(debugLocation);
+        }
+
+        return result;
+    }
+
+    // find locations unique by line number and source name
+    // (used in 'check_ReferenceType_locationsOfLine' and
+    // 'check_Method_locationsOfLine' to find all line numbers available for
+    // ReferenceType or Method)
+    static protected Set<DebugLocation> allUniqueLocations(List<DebugLocation> debugLocations) {
+        Set<DebugLocation> result = new TreeSet<DebugLocation>();
+
+        for (DebugLocation debugLocation : debugLocations) {
+            if (!result.contains(debugLocation)) {
+                result.add(debugLocation);
+            }
+        }
+
+        return result;
+    }
+
+    // check is list of Locations contains only expected locations
+    protected void compareLocations(List<Location> locations, List<DebugLocation> expectedLocations, String stratum) {
+        boolean success = true;
+
+        List<Location> tempLocations = new LinkedList<Location>(locations);
+
+        List<DebugLocation> tempExpectedLocations = new LinkedList<DebugLocation>(expectedLocations);
+
+        for(Iterator<Location> locationsIterator = tempLocations.iterator(); locationsIterator.hasNext();) {
+            boolean isExpected = false;
+            Location location = locationsIterator.next();
+
+            for(Iterator<DebugLocation> expectedLocationsIterator = tempExpectedLocations.iterator(); expectedLocationsIterator.hasNext();) {
+                DebugLocation expectedLocation = expectedLocationsIterator.next();
+                if (expectedLocation.compare(location, stratum)) {
+                    isExpected = true;
+                    locationsIterator.remove();
+                    expectedLocationsIterator.remove();
+                    break;
+                }
+            }
+            if (!isExpected) {
+                success = false;
+                log.complain("Location " + location + " were not found in expected locations");
+            }
+        }
+
+        if (tempLocations.size() != 0) {
+            success = false;
+            setSuccess(false);
+            log.complain("Not all locations were found in expected");
+        }
+
+        if (tempExpectedLocations.size() != 0) {
+            success = false;
+            setSuccess(false);
+            log.complain("Following expected locations were not found in received");
+            for (DebugLocation expectedLocation : tempExpectedLocations) {
+                log.complain(expectedLocation.toString());
+            }
+        }
+
+        if (!success) {
+            setSuccess(false);
+            log.complain("Expected and actual locations differ");
+
+            log.complain("Actual locations: ");
+            for (Location location : locations) {
+                log.complain(locationToString(location, stratum));
+            }
+
+            log.complain("Expected locations: ");
+            for (DebugLocation expectedLocation : expectedLocations) {
+                log.complain(expectedLocation.toString());
+            }
+        }
+    }
+
+    // test all SDE related methods of ReferenceType
+    protected void checkReferenceType(String stratum, ReferenceType referenceType, List<String> expectedSourceNames,
+            List<String> expectedSourcePaths, List<DebugLocation> expectedLocations) {
+        log.display("Check sourceNames");
+        check_ReferenceType_sourceNames(referenceType, stratum, expectedSourceNames);
+        log.display("Check sourcePaths");
+        check_ReferenceType_sourcePaths(referenceType, stratum, expectedSourcePaths);
+        log.display("Check allLocations");
+        check_ReferenceType_allLineLocations(referenceType, stratum, expectedLocations);
+        log.display("Check locationsOfLine");
+        check_ReferenceType_locationsOfLine(referenceType, stratum, false, expectedLocations);
+
+        for (Method method : referenceType.methods()) {
+            List<DebugLocation> expectedLocationsOfMethod = locationsOfMethod(expectedLocations, method.name());
+
+            log.display("Check allLineLocations for method '" + method.name() + "'");
+            check_Method_allLineLocations(method, stratum, expectedLocationsOfMethod);
+            log.display("Check locationsOfLine for method '" + method.name() + "'");
+            check_Method_locationsOfLine(method, stratum, false, expectedLocationsOfMethod);
+        }
+    }
+
+    // check is 'ReferenceType.sourceNames' returns only expected sources
+    protected void check_ReferenceType_sourceNames(ReferenceType referenceType, String stratum,
+            List<String> expectedSourceNames) {
+        try {
+            if (stratum == null) {
+                String sourceName = referenceType.sourceName();
+                String expectedSourceName = expectedSourceNames.get(0);
+
+                if (!sourceName.equals(expectedSourceName)) {
+                    setSuccess(false);
+                    log.complain("Unexpected result of ReferenceType.sourceName(): " + sourceName + ", expected is "
+                            + expectedSourceName);
+                }
+            } else {
+                boolean success = true;
+
+                List<String> sourceNames = referenceType.sourceNames(stratum);
+
+                if (!expectedSourceNames.containsAll(sourceNames)) {
+                    success = false;
+                    log.complain("ReferenceType.sourceNames() returns unexpected names");
+                }
+
+                if (!sourceNames.containsAll(expectedSourceNames)) {
+                    success = false;
+                    log.complain("Not all expected source names was returned by ReferenceType.sourceNames()");
+                }
+
+                if (!success) {
+                    log.complain("Expected source names:");
+                    for (String name : expectedSourceNames)
+                        log.complain(name);
+                    log.complain("Actual source names:");
+                    for (String name : sourceNames)
+                        log.complain(name);
+                }
+            }
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+    }
+
+    // check is 'ReferenceType.sourcePaths' returns only expected paths
+    protected void check_ReferenceType_sourcePaths(ReferenceType referenceType, String stratum,
+            List<String> expectedSourcePaths) {
+        try {
+            boolean success = true;
+
+            List<String> sourcePaths = referenceType.sourcePaths(stratum);
+
+            if (!expectedSourcePaths.containsAll(sourcePaths)) {
+                success = false;
+                log.complain("ReferenceType.sourcePaths() returns unexpected paths");
+            }
+
+            if (!sourcePaths.containsAll(expectedSourcePaths)) {
+                success = false;
+                log.complain("Not all expected paths was returned by ReferenceType.sourcePaths()");
+            }
+
+            if (!success) {
+                log.complain("Expected paths:");
+                for (String path : expectedSourcePaths)
+                    log.complain(path);
+                log.complain("Actual paths:");
+                for (String path : sourcePaths)
+                    log.complain(path);
+            }
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+    }
+
+    // check that method 'ReferenceType.allLineLocations' returns only expected
+    // locations
+    protected void check_ReferenceType_allLineLocations(ReferenceType referenceType, String stratum,
+            List<DebugLocation> expectedLocations) {
+        try {
+            List<Location> locations = referenceType.allLineLocations();
+            compareLocations(locations, expectedLocations, stratum);
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+    }
+
+    // check that method 'Method.allLineLocations' returns only expected
+    // locations
+    protected void check_Method_allLineLocations(Method method, String stratum,
+            List<DebugLocation> expectedLocationsOfMethod) {
+        try {
+            List<Location> methodAllLineLocations = method.allLineLocations();
+            compareLocations(methodAllLineLocations, expectedLocationsOfMethod, stratum);
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+    }
+
+    // for each line available for method check result of
+    // 'Method.locationsOfLine'
+    protected void check_Method_locationsOfLine(Method method, String stratum, boolean allSources,
+            List<DebugLocation> expectedLocationsOfMethod) {
+        try {
+            for (DebugLocation uniqueLocation : allUniqueLocations(expectedLocationsOfMethod)) {
+                String sourceName = allSources ? null : uniqueLocation.sourceName;
+
+                List<DebugLocation> expectedLocationsOfLine = locationsOfLine(
+                        expectedLocationsOfMethod,
+                        sourceName,
+                        uniqueLocation.inputLine);
+
+                List<Location> locationsOfLine = (stratum == null) ? method.locationsOfLine(uniqueLocation.inputLine)
+                        : method.locationsOfLine(stratum, sourceName, uniqueLocation.inputLine);
+
+                compareLocations(locationsOfLine, expectedLocationsOfLine, stratum);
+            }
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+    }
+
+    // for each line available for ReferenceType check result of
+    // 'ReferenceType.locationsOfLine'
+    protected void check_ReferenceType_locationsOfLine(ReferenceType referenceType, String stratum, boolean allSources,
+            List<DebugLocation> expectedLocations) {
+        try {
+            for (DebugLocation uniqueLocation : allUniqueLocations(expectedLocations)) {
+                String sourceName = allSources ? null : uniqueLocation.sourceName;
+
+                List<DebugLocation> expectedLocationsOfLine = locationsOfLine(
+                        expectedLocations,
+                        sourceName,
+                        uniqueLocation.inputLine);
+
+                List<Location> locations = (stratum == null) ? referenceType.locationsOfLine(uniqueLocation.inputLine)
+                        : referenceType.locationsOfLine(stratum, sourceName, uniqueLocation.inputLine);
+
+                compareLocations(locations, expectedLocationsOfLine, stratum);
+            }
+        } catch (AbsentInformationException e) {
+            setSuccess(false);
+            log.complain("Unexpected exception: " + e);
+            e.printStackTrace(log.getOutStream());
+        }
+
+    }
+
+    // check that method 'ReferenceType.availableStrata' returns only expected
+    // stratums
+    protected void check_ReferenceType_availableStrata(ReferenceType referenceType, List<String> expectedStrata) {
+        boolean success = true;
+
+        List<String> strata = referenceType.availableStrata();
+
+        if (!expectedStrata.containsAll(strata)) {
+            success = false;
+            log.complain("ReferenceType.availableStrata() returns unexpected values");
+        }
+
+        if (!strata.containsAll(expectedStrata)) {
+            success = false;
+            log.complain("Not all expected stratums was returned by ReferenceType.availableStrata()");
+        }
+
+        if (!success) {
+            log.complain("Expected stratums:");
+            for (String name : expectedStrata)
+                log.complain(name);
+            log.complain("Actual stratums:");
+            for (String name : strata)
+                log.complain(name);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SmapGenerator.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi.sde;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents a source map (SMAP), which serves to associate lines
+ * of the input source to lines in the generated output source in the
+ * final .class file, according to the JSR-045 spec.
+ */
+public class SmapGenerator {
+
+    //*********************************************************************
+    // Overview
+
+    /*
+     * The SMAP syntax is reasonably straightforward.  The purpose of this
+     * class is currently twofold:
+     *  - to provide a simple but low-level Java interface to build
+     *    a logical SMAP
+     *  - to serialize this logical SMAP for eventual inclusion directly
+     *    into a .class file.
+     */
+
+
+    //*********************************************************************
+    // Private state
+
+    private String outputFileName;
+    private String defaultStratum = "Java";
+    private List<SmapStratum> strata = new ArrayList<SmapStratum>();
+    private List<String> embedded = new ArrayList<String>();
+    private boolean doEmbedded = true;
+
+    //*********************************************************************
+    // Methods for adding mapping data
+
+    /**
+     * Sets the filename (without path information) for the generated
+     * source file.  E.g., "foo$jsp.java".
+     */
+    public synchronized void setOutputFileName(String x) {
+        outputFileName = x;
+    }
+
+    /**
+     * Adds the given SmapStratum object, representing a Stratum with
+     * logically associated FileSection and LineSection blocks, to
+     * the current SmapGenerator.  If <tt>default</tt> is true, this
+     * stratum is made the default stratum, overriding any previously
+     * set default.
+     *
+     * @param stratum the SmapStratum object to add
+     * @param defaultStratum if <tt>true</tt>, this SmapStratum is considered
+     *                to represent the default SMAP stratum unless
+     *                overwritten
+     */
+    public synchronized void addStratum(SmapStratum stratum,
+            boolean defaultStratum) {
+        strata.add(stratum);
+        if (defaultStratum)
+            this.defaultStratum = stratum.getStratumName();
+    }
+
+    /**
+     * Adds the given string as an embedded SMAP with the given stratum name.
+     *
+     * @param smap the SMAP to embed
+     * @param stratumName the name of the stratum output by the compilation
+     *                    that produced the <tt>smap</tt> to be embedded
+     */
+    public synchronized void addSmap(String smap, String stratumName) {
+        embedded.add("*O " + stratumName + "\n"
+                + smap
+                + "*C " + stratumName + "\n");
+    }
+
+    /**
+     * Instructs the SmapGenerator whether to actually print any embedded
+     * SMAPs or not.  Intended for situations without an SMAP resolver.
+     *
+     * @param status If <tt>false</tt>, ignore any embedded SMAPs.
+     */
+    public void setDoEmbedded(boolean status) {
+        doEmbedded = status;
+    }
+
+    public File saveToFile(String fileName)
+    throws IOException
+    {
+        File file = new File(fileName);
+
+        file.createNewFile();
+
+        FileOutputStream outStream = new FileOutputStream(file);
+        outStream.write(getString().getBytes());
+        outStream.close();
+
+        return file;
+    }
+
+    //*********************************************************************
+    // Methods for serializing the logical SMAP
+
+    public synchronized String getString() {
+        // check state and initialize buffer
+        if (outputFileName == null)
+            throw new IllegalStateException();
+        StringBuffer out = new StringBuffer();
+
+        // start the SMAP
+        out.append("SMAP\n");
+        out.append(outputFileName + '\n');
+        out.append(defaultStratum + '\n');
+
+        // include embedded SMAPs
+        if (doEmbedded) {
+            int nEmbedded = embedded.size();
+            for (int i = 0; i < nEmbedded; i++) {
+                out.append(embedded.get(i));
+            }
+        }
+
+        // print our StratumSections, FileSections, and LineSections
+        int nStrata = strata.size();
+        for (int i = 0; i < nStrata; i++) {
+            SmapStratum s = (SmapStratum) strata.get(i);
+            out.append(s.getString());
+        }
+
+        // end the SMAP
+        out.append("*E\n");
+
+        return out.toString();
+    }
+
+    public String toString() { return getString(); }
+
+    //*********************************************************************
+    // For testing (and as an example of use)...
+
+    public static void main(String args[]) {
+        SmapGenerator g = new SmapGenerator();
+        g.setOutputFileName("foo.java");
+        SmapStratum s = new SmapStratum("JSP");
+        s.addFile("foo.jsp");
+        s.addFile("bar.jsp", "/foo/foo/bar.jsp");
+        s.addLineData(1, "foo.jsp", 1, 1, 1);
+        s.addLineData(2, "foo.jsp", 1, 6, 1);
+        s.addLineData(3, "foo.jsp", 2, 10, 5);
+        s.addLineData(20, "bar.jsp", 1, 30, 1);
+        g.addStratum(s, true);
+        System.out.print(g);
+
+        System.out.println("---");
+
+        SmapGenerator embedded = new SmapGenerator();
+        embedded.setOutputFileName("blargh.tier2");
+        s = new SmapStratum("Tier2");
+        s.addFile("1.tier2");
+        s.addLineData(1, "1.tier2", 1, 1, 1);
+        embedded.addStratum(s, true);
+        g.addSmap(embedded.toString(), "JSP");
+        System.out.println(g);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/SmapStratum.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jdi.sde;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents the line and file mappings associated with a JSR-045
+ * "stratum".
+ */
+public class SmapStratum
+{
+
+    //*********************************************************************
+    // Class for storing LineInfo data
+
+    /**
+     * Represents a single LineSection in an SMAP, associated with
+     * a particular stratum.
+     */
+    public static class LineInfo {
+        private int inputStartLine = -1;
+        private int outputStartLine = -1;
+        private int lineFileID = 0;
+        private int inputLineCount = 1;
+        private int outputLineIncrement = 1;
+        private boolean lineFileIDSet = false;
+
+        /** Sets InputStartLine. */
+        public void setInputStartLine(int inputStartLine) {
+            if (inputStartLine < 0)
+                throw new IllegalArgumentException("" + inputStartLine);
+            this.inputStartLine = inputStartLine;
+        }
+
+        /** Sets OutputStartLine. */
+        public void setOutputStartLine(int outputStartLine) {
+            if (outputStartLine < 0)
+                throw new IllegalArgumentException("" + outputStartLine);
+            this.outputStartLine = outputStartLine;
+        }
+
+        /**
+         * Sets lineFileID.  Should be called only when different from
+         * that of prior LineInfo object (in any given context) or 0
+         * if the current LineInfo has no (logical) predecessor.
+         * <tt>LineInfo</tt> will print this file number no matter what.
+         */
+        public void setLineFileID(int lineFileID) {
+            if (lineFileID < 0)
+                throw new IllegalArgumentException("" + lineFileID);
+            this.lineFileID = lineFileID;
+            this.lineFileIDSet = true;
+        }
+
+        /** Sets InputLineCount. */
+        public void setInputLineCount(int inputLineCount) {
+            if (inputLineCount < 0)
+                throw new IllegalArgumentException("" + inputLineCount);
+            this.inputLineCount = inputLineCount;
+        }
+
+        /** Sets OutputLineIncrement. */
+        public void setOutputLineIncrement(int outputLineIncrement) {
+            if (outputLineIncrement < 0)
+                throw new IllegalArgumentException("" + outputLineIncrement);
+            this.outputLineIncrement = outputLineIncrement;
+        }
+
+        /**
+         * Retrieves the current LineInfo as a String, print all values
+         * only when appropriate (but LineInfoID if and only if it's been
+         * specified, as its necessity is sensitive to context).
+         */
+        public String getString() {
+            if (inputStartLine == -1 || outputStartLine == -1)
+                throw new IllegalStateException();
+            StringBuffer out = new StringBuffer();
+            out.append(inputStartLine);
+            if (lineFileIDSet)
+                out.append("#" + lineFileID);
+            if (inputLineCount != 1)
+                out.append("," + inputLineCount);
+            out.append(":" + outputStartLine);
+            if (outputLineIncrement != 1)
+                out.append("," + outputLineIncrement);
+            out.append('\n');
+            return out.toString();
+        }
+
+        public String toString() {
+            return getString();
+        }
+    }
+
+    //*********************************************************************
+    // Private state
+
+    private String stratumName;
+    private List<String> fileNameList;
+    private List<String> filePathList;
+    private List<LineInfo> lineData;
+    private int lastFileID;
+
+    //*********************************************************************
+    // Constructor
+
+    /**
+     * Constructs a new SmapStratum object for the given stratum name
+     * (e.g., JSP).
+     *
+     * @param stratumName the name of the stratum (e.g., JSP)
+     */
+    public SmapStratum(String stratumName) {
+        this.stratumName = stratumName;
+        fileNameList = new ArrayList<String>();
+        filePathList = new ArrayList<String>();
+        lineData = new ArrayList<LineInfo>();
+        lastFileID = 0;
+    }
+
+    //*********************************************************************
+    // Methods to add mapping information
+
+    /**
+     * Adds record of a new file, by filename.
+     *
+     * @param filename the filename to add, unqualified by path.
+     */
+    public void addFile(String filename) {
+        addFile(filename, filename);
+    }
+
+    /**
+     * Adds record of a new file, by filename and path.  The path
+     * may be relative to a source compilation path.
+     *
+     * @param filename the filename to add, unqualified by path
+     * @param filePath the path for the filename, potentially relative
+     *                 to a source compilation path
+     */
+    public void addFile(String filename, String filePath) {
+        int pathIndex = filePathList.indexOf(filePath);
+        if (pathIndex == -1) {
+            fileNameList.add(filename);
+            filePathList.add(filePath);
+        }
+    }
+
+    /**
+     * Adds complete information about a simple line mapping.  Specify
+     * all the fields in this method; the back-end machinery takes care
+     * of printing only those that are necessary in the final SMAP.
+     * (My view is that fields are optional primarily for spatial efficiency,
+     * not for programmer convenience.  Could always add utility methods
+     * later.)
+     *
+     * @param inputStartLine starting line in the source file
+     *        (SMAP <tt>InputStartLine</tt>)
+     * @param inputFileName the filepath (or name) from which the input comes
+     *        (yields SMAP <tt>LineFileID</tt>)  Use unqualified names
+     *        carefully, and only when they uniquely identify a file.
+     * @param inputLineCount the number of lines in the input to map
+     *        (SMAP <tt>LineFileCount</tt>)
+     * @param outputStartLine starting line in the output file
+     *        (SMAP <tt>OutputStartLine</tt>)
+     * @param outputLineIncrement number of output lines to map to each
+     *        input line (SMAP <tt>OutputLineIncrement</tt>).  <i>Given the
+     *        fact that the name starts with "output", I continuously have
+     *        the subconscious urge to call this field
+     *        <tt>OutputLineExcrement</tt>.</i>
+     */
+    public void addLineData(
+            int inputStartLine,
+            String inputFileName,
+            int inputLineCount,
+            int outputStartLine,
+            int outputLineIncrement) {
+        // check the input - what are you doing here??
+        int fileIndex = fileNameList.indexOf(inputFileName);
+        if (fileIndex == -1) // still
+            throw new IllegalArgumentException(
+                    "inputFileName: " + inputFileName);
+
+        //Jasper incorrectly SMAPs certain Nodes, giving them an
+        //outputStartLine of 0.  This can cause a fatal error in
+        //optimizeLineSection, making it impossible for Jasper to
+        //compile the JSP.  Until we can fix the underlying
+        //SMAPping problem, we simply ignore the flawed SMAP entries.
+        if (outputStartLine == 0)
+            return;
+
+        // build the LineInfo
+        LineInfo li = new LineInfo();
+        li.setInputStartLine(inputStartLine);
+        li.setInputLineCount(inputLineCount);
+        li.setOutputStartLine(outputStartLine);
+        li.setOutputLineIncrement(outputLineIncrement);
+        if (fileIndex != lastFileID)
+            li.setLineFileID(fileIndex);
+        lastFileID = fileIndex;
+
+        // save it
+        lineData.add(li);
+    }
+
+    //*********************************************************************
+    // Methods to retrieve information
+
+    /**
+     * Returns the name of the stratum.
+     */
+    public String getStratumName() {
+        return stratumName;
+    }
+
+    /**
+     * Returns the given stratum as a String:  a StratumSection,
+     * followed by at least one FileSection and at least one LineSection.
+     */
+    public String getString() {
+        // check state and initialize buffer
+        if (fileNameList.size() == 0 || lineData.size() == 0)
+            return null;
+
+        StringBuffer out = new StringBuffer();
+
+        // print StratumSection
+        out.append("*S " + stratumName + "\n");
+
+        // print FileSection
+        out.append("*F\n");
+        int bound = fileNameList.size();
+        for (int i = 0; i < bound; i++) {
+            if (filePathList.get(i) != null) {
+                out.append("+ " + i + " " + fileNameList.get(i) + "\n");
+                // Source paths must be relative, not absolute, so we
+                // remove the leading "/", if one exists.
+                String filePath = (String)filePathList.get(i);
+                if (filePath.startsWith("/")) {
+                    filePath = filePath.substring(1);
+                }
+                out.append(filePath + "\n");
+            } else {
+                out.append(i + " " + fileNameList.get(i) + "\n");
+            }
+        }
+
+        // print LineSection
+        out.append("*L\n");
+        bound = lineData.size();
+        for (int i = 0; i < bound; i++) {
+            LineInfo li = (LineInfo)lineData.get(i);
+            out.append(li.getString());
+        }
+
+        return out.toString();
+    }
+
+    public String toString() {
+        return getString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/sde/TestClass1.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//    THIS TEST IS LINE NUMBER SENSITIVE
+
+package nsk.share.jdi.sde;
+
+// Class contains 3 methods with several locations, do not edit this file because of line numbers are hardcoded in tests
+public class TestClass1 {
+    public TestClass1()
+    {
+        super(); // SDEDebugger.INIT_LINE
+        int i = 0;
+        i++;
+        i++;
+        i++;
+        i++;
+        i++;
+    }
+
+    public void sde_testMethod1()
+    {
+        int i = 0; // SDEDebugger.METHOD1_LINE
+        i++;
+        i++;
+        i++;
+        i++;
+        i++;
+        i++;
+    }
+
+    public void sde_testMethod2()
+    {
+        int i = 0; // SDEDebugger.METHOD2_LINE
+        i++;
+        i++;
+        i++;
+        i++;
+        i++;
+        i++;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/JNIreferences.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "jni.h"
+#include <stdlib.h>
+#include "nsk_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_PTR
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG_2(x, y) y
+#define JNI_ENV_ARG_3(x, y, z) y, z
+#define JNI_ENV_ARG_4(x, y, z, a) y, z, a
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG_2(x,y) x, y
+#define JNI_ENV_ARG_3(x, y, z) x, y, z
+#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+static jobject* globalReferences = NULL;
+static jweak* weakReferences = NULL;
+
+JNIEXPORT jint JNICALL
+Java_nsk_share_ReferringObject_createJNIGlobalReferenceNative(JNIEnv *env,
+        jobject thisObject, jobject object, jint maxJNIGlobalReferences)
+{
+        jint i;
+        jint result = -1;
+
+        if(globalReferences == NULL)
+        {
+                globalReferences = (jobject*)malloc(sizeof(jobject) * maxJNIGlobalReferences);
+
+                if(globalReferences == NULL)
+                {
+                        NSK_COMPLAIN0("malloc return NULL\n");
+                        return -1;
+                }
+
+                for(i = 0; i < maxJNIGlobalReferences; i++)
+                {
+                        globalReferences[i] = NULL;
+                }
+        }
+
+        for(i = 0; i < maxJNIGlobalReferences; i++)
+        {
+                jobject reference = globalReferences[i];
+
+                if(reference == NULL)
+                {
+                        reference = JNI_ENV_PTR(env)->NewGlobalRef(JNI_ENV_ARG_2(env, object));
+
+                        if(reference == NULL)
+                        {
+                                NSK_COMPLAIN0("NewGlobalRef return NULL\n");
+
+                                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "NewGlobalRef return NULL"));
+                        }
+
+                        globalReferences[i] = reference;
+
+                        result = i;
+
+                        break;
+                }
+        }
+
+        return result;
+}
+
+JNIEXPORT void JNICALL
+Java_nsk_share_ReferringObject_deleteJNIGlobalReferenceNative(JNIEnv *env,
+        jobject thisObject, jint index)
+{
+        jobject reference = globalReferences[index];
+
+        if(reference == NULL)
+        {
+                NSK_COMPLAIN1("globalReferences[%d] = NULL, possible wrong index is passed\n", index);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestBug")), "Requested globalReferences[] element is NULL, possible wrong index is passed"));
+        }
+
+        JNI_ENV_PTR(env)->DeleteGlobalRef(JNI_ENV_ARG_2(env, reference));
+
+        globalReferences[index] = NULL;
+}
+
+
+JNIEXPORT void JNICALL
+Java_nsk_share_ReferringObject_createJNILocalReferenceNative(JNIEnv *env,
+        jobject thisObject, jobject object, jobject createWicket, jobject deleteWicket)
+{
+        jobject reference = JNI_ENV_PTR(env)->NewLocalRef(JNI_ENV_ARG_2(env, object));
+        jclass klass;
+
+        if(reference == NULL)
+        {
+                NSK_COMPLAIN0("NewLocalRef return NULL\n");
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "NewLocalRef return NULL"));
+        }
+
+        klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, createWicket));
+
+        // notify another thread that JNI local reference has been created
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, createWicket, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, klass, "unlock", "()V"))));
+
+        // wait till JNI local reference can be released (it will heppen then we will leave the method)
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, deleteWicket, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, klass, "waitFor", "()V"))));
+}
+
+JNIEXPORT jint JNICALL
+Java_nsk_share_ReferringObject_createJNIWeakReferenceNative(JNIEnv *env,
+        jobject thisObject, jobject object, jint maxJNIWeakReferences)
+{
+        jint i;
+        jint result = -1;
+
+        if(weakReferences == NULL)
+        {
+                weakReferences = (jweak*)malloc(sizeof(jweak) * maxJNIWeakReferences);
+
+                if(weakReferences == NULL)
+                {
+                        NSK_COMPLAIN0("malloc return NULL\n");
+
+                        return -1;
+                }
+
+                for(i = 0; i < maxJNIWeakReferences; i++)
+                {
+                        weakReferences[i] = NULL;
+                }
+        }
+
+        for(i = 0; i < maxJNIWeakReferences; i++)
+        {
+                jobject reference = weakReferences[i];
+
+                if(reference == NULL)
+                {
+                        reference = JNI_ENV_PTR(env)->NewWeakGlobalRef(JNI_ENV_ARG_2(env, object));
+
+                        if(reference == NULL)
+                        {
+                                NSK_COMPLAIN0("NewWeakGlobalRef return NULL\n");
+
+                                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "NewWeakGlobalRef return NULL"));
+                        }
+
+                        weakReferences[i] = reference;
+
+                        result = i;
+
+                        break;
+                }
+        }
+
+        return result;
+}
+
+JNIEXPORT void JNICALL
+Java_nsk_share_ReferringObject_deleteJNIWeakReferenceNative(JNIEnv *env,
+        jobject thisObject, jint index)
+{
+        jweak reference = weakReferences[index];
+
+        if(reference == NULL)
+        {
+                NSK_COMPLAIN1("weakReferences[%d] = NULL, possible wrong index is passed\n", index);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestBug")), "Requested weakReferences[] element is NULL, possible wrong index is passed"));
+        }
+
+        if(JNI_ENV_PTR(env)->IsSameObject(JNI_ENV_ARG_3(env, reference, NULL)) == JNI_TRUE)
+        {
+                NSK_COMPLAIN0("TEST BUG: Weak reference was collected\n");
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestBug")), "TEST BUG: Weak reference was collected"));
+        }
+
+        JNI_ENV_PTR(env)->DeleteWeakGlobalRef(JNI_ENV_ARG_2(env, reference));
+
+        weakReferences[index] = NULL;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/README	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,61 @@
+Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and\\\/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+---------------------------------------------------------------------------------
+
+This directory contains source files of testbase_nsk JNI framework,
+which provides support for JNI tests and accessing JNI environment.
+
+    Source files:
+        jni_tools.h
+        jni_tools.c
+
+    Naming conventions:
+        macroses:  NSK_JNI_*
+        functions: nsk_JNI_*
+
+---------------------------------------------------------------------------------
+
+jni_tools.h
+
+Provides functions and macroses for invocation of JNI functions
+and checking JNI errors and pending exceptions:
+
+    NSK_JNI_VERIFY(jni, action)
+    NSK_JNI_VERIFY_NEGATIVE(jni, action)
+
+Typical example of usage of NSK_JNI_VERIFY and NSK_CPP_STUB macroses
+for invokation of JNI functions:
+
+    // jni->FindClass(jni, class_name)
+    if (!NSK_JNI_VERIFY(jni,
+            NSK_CPP_STUB2(FindClass, jni, class_name) != NULL)) {
+        return JNI_ERR;
+    }
+
+or with saving obtained data:
+
+    // cls = jni->FindClass(jni, class_name)
+    if (!NSK_JNI_VERIFY(jni, (cls =
+            NSK_CPP_STUB2(FindClass, jni, class_name)) != NULL)) {
+        return JNI_ERR;
+    }
+
+---------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/jni_tools.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+/*************************************************************/
+#if (defined(WIN32) || defined(_WIN32))
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+/*************************************************************/
+
+#include "jni.h"
+
+/*************************************************************/
+
+#include "nsk_tools.h"
+#include "jni_tools.h"
+
+/*************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+
+int nsk_jni_check_exception(JNIEnv* jni, const char file[], int line)
+{
+    jthrowable throwable;
+
+    NSK_TRACE(throwable = NSK_CPP_STUB1(ExceptionOccurred, jni));
+    if (throwable != NULL) {
+        nsk_lcomplain(file, line, "Exception in JNI call (cleared):\n");
+        NSK_TRACE(NSK_CPP_STUB1(ExceptionDescribe, jni));
+        NSK_TRACE(NSK_CPP_STUB1(ExceptionClear, jni));
+        return NSK_TRUE;
+    }
+    return NSK_FALSE;
+}
+
+int nsk_jni_lverify(int positive, JNIEnv* jni, int status,
+                        const char file[], int line, const char format[], ...)
+{
+    int failure=0;
+    int negative = !positive;
+    va_list ap;
+    va_start(ap,format);
+
+    nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap);
+    if (status == negative) {
+        nsk_lvcomplain(file,line,format,ap);
+        nsk_printf("#   verified JNI assertion is FALSE\n");
+        failure=1;
+    }
+
+    failure = nsk_jni_check_exception(jni, file, line) || failure;
+
+    va_end(ap);
+    return !failure;
+}
+
+int nsk_jni_lverify_void(JNIEnv* jni, const char file[], int line,
+                            const char format[], ...)
+{
+    int failure=0;
+    va_list ap;
+    va_start(ap,format);
+
+    nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap);
+    failure = nsk_jni_check_exception(jni, file, line);
+
+    if (failure)
+        nsk_lvcomplain(file,line,format,ap);
+
+    va_end(ap);
+    return !failure;
+}
+
+char *jlong_to_string(jlong value, char *string) {
+    char buffer[32];
+    char *pbuf, *pstr;
+
+    pstr = string;
+    if (value == 0) {
+        *pstr++ = '0';
+    } else {
+        if (value < 0) {
+            *pstr++ = '-';
+            value = -value;
+        }
+        pbuf = buffer;
+        while (value != 0) {
+            *pbuf++ = '0' + (char)(value % 10);
+            value = value / 10;
+        }
+        while (pbuf != buffer) {
+            *pstr++ = *--pbuf;
+        }
+    }
+    *pstr = '\0';
+
+    return string;
+}
+
+char *julong_to_string(julong value, char *string) {
+    char buffer[32];
+    char *pbuf, *pstr;
+
+    pstr = string;
+    if (value == 0) {
+        *pstr++ = '0';
+    } else {
+        pbuf = buffer;
+        while (value != 0) {
+            *pbuf++ = '0' + (char)(value % 10);
+            value = value / 10;
+        }
+        while (pbuf != buffer) {
+            *pstr++ = *--pbuf;
+        }
+    }
+    *pstr = '\0';
+
+    return string;
+}
+
+void mssleep(long millis) {
+#if (defined(WIN32) || defined(_WIN32))
+   Sleep(millis);
+#else
+   /* Using select for portable sleep */
+   /* Not using usleep because of it's possible interaction with SIGALRM */
+   struct timeval timeout;
+   timeout.tv_sec = millis / 1000;
+   timeout.tv_usec = (millis % 1000) * 1000;
+   select(0, NULL, NULL, NULL, &timeout);
+#endif
+}
+
+void
+jni_print_vmargs(JavaVMInitArgs vmargs)
+{
+   int i = 0;
+
+   printf("JavaVMInitArgs:\n");
+   printf(" version = %d\n", vmargs.version);
+   printf(" ignoreUnrecognized = %d\n", vmargs.ignoreUnrecognized);
+
+   printf(" vmargs.nOptions = %d\n", vmargs.nOptions);
+   for (i = 0; i < vmargs.nOptions; i++) {
+      printf("   options[%d].optionString = %s\n", i, vmargs.options[i].optionString);
+      printf("   options[%d].extraInfo = %p\n", i, vmargs.options[i].extraInfo);
+   }
+}
+
+JavaVMOption*
+jni_create_vmoptions(int size, char *args[], int argsCnt)
+{
+   int i;
+   JavaVMOption *options = NULL;
+
+   if (size <= 0)
+      return options;
+
+   options = (JavaVMOption*)calloc(size, sizeof(JavaVMOption));
+
+   for (i=0; i<argsCnt; i++)
+      options[i].optionString = args[i];
+
+   return options;
+}
+
+/*************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jni/jni_tools.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NSK_JNI_TOOLS_DEFINED
+#define NSK_JNI_TOOLS_DEFINED
+
+/*************************************************************/
+
+#include "jni.h"
+
+/*************************************************************/
+
+#include "nsk_tools.h"
+
+/*************************************************************/
+
+/* printf format specifier for jlong */
+#ifdef _WIN32
+
+#define LL "I64"
+#include <STDDEF.H>
+
+#else // !_WIN32
+
+#include <stdint.h>
+
+#ifdef _LP64
+#define LL "l"
+#else
+#define LL "ll"
+#endif
+
+#endif // !_WIN32
+
+/**
+ * Additional Java basic types
+ */
+
+#ifdef _WIN32
+    typedef unsigned __int64 julong;
+#else
+    typedef unsigned long long julong;
+#endif
+
+/*************************************************************/
+
+/**
+ * Execute action with JNI call, check result for true and
+ * pending exception and complain error if required.
+ * Also trace action execution if tracing mode enabled.
+ */
+#define NSK_JNI_VERIFY(jni, action)  \
+    (nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action), \
+        nsk_jni_lverify(NSK_TRUE,jni,action,__FILE__,__LINE__,"%s\n",#action))
+
+/**
+ * Execute action with JNI call, check result for false and
+ * pending exception and complain error if required.
+ * Also trace action execution if tracing mode enabled.
+ */
+#define NSK_JNI_VERIFY_NEGATIVE(jni,action)  \
+    (nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action), \
+        nsk_jni_lverify(NSK_FALSE,jni,action,__FILE__,__LINE__,"%s\n",#action))
+
+/**
+ * Execute action with JNI call, check result for
+ * pending exception and complain error if required.
+ * Also trace action execution if tracing mode enabled.
+ */
+#define NSK_JNI_VERIFY_VOID(jni,action)  \
+    (nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action), \
+        action, \
+        nsk_jni_lverify_void(jni, __FILE__,__LINE__,"%s\n",#action))
+
+/*************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+
+/**
+ * If positive, assert status is true; or
+ * if !positive, assert status is not true.
+ * Assert means: complain if the assertion is false.
+ * Return the assertion value, either NSK_TRUE or NSK_FALSE.
+ * Anyway, trace if "nsk_tools" mode is verbose and
+ * print information about pending exceptions if status is false.
+ */
+int nsk_jni_lverify(int positive, JNIEnv* jni, int status,
+                        const char file[], int line, const char format[], ...);
+
+/**
+ * If positive, assert status is true; or
+ * if !positive, assert status is not true.
+ * Assert means: complain if the assertion is false.
+ * Return the assertion value, either NSK_TRUE or NSK_FALSE.
+ * Anyway, trace if "nsk_tools" mode is verbose and
+ * print information about pending exceptions if status is false.
+ */
+int nsk_jni_lverify_void(JNIEnv* jni, const char file[], int line,
+                            const char format[], ...);
+
+/**
+ * Checks if pending exception exists and then prints error message
+ * with exception description, clears pending exception amd return 1.
+ * Otherwise, does noting and returns 0,
+ */
+int nsk_jni_check_exception(JNIEnv* jni, const char file[], int line);
+
+/**
+ * Convert the digits of the given value argument to a null-terminated
+ * character string and store the result (up to 32 bytes) in string.
+ * If value is negative, the first character of the stored string is
+ * the minus sign (-). The function returns a pointer to the begining
+ * of the result string.
+ */
+char *jlong_to_string(jlong value, char *string);
+
+/**
+ * Convert the digits of the given value argument to a null-terminated
+ * character string and store the result (up to 32 bytes) in string.
+ * The function returns a pointer to the begining of the result string.
+ */
+char *julong_to_string(julong value, char *string);
+
+/**
+ * Sleep for given number of milliseconds.
+ */
+void mssleep(long millis);
+
+/**
+ * Create JavaVMOption array of size 'size' and fills
+ * first argsCnt elements from args[].
+ * Callee is responsible to free JavaVMOption*.
+ * No other memory deallocations are required.
+ */
+JavaVMOption* jni_create_vmoptions(int size, char *args[], int argsCnt);
+
+/**
+ * Print JavaVMInitArgs values to stdout.
+ */
+void jni_print_vmargs(JavaVMInitArgs vmargs);
+
+/*************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************************/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//    THIS TEST IS LINE NUMBER SENSITIVE
+
+package nsk.share.jpda;
+
+import java.io.*;
+import java.util.*;
+import nsk.share.*;
+import nsk.share.test.*;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+/*
+ * Class can be used as base debuggee class in jdi and jdwp tests.
+ * Class contains common method for initializing log, pipe, vm, and several common auxiliary methods.  Subclass should implement parseCommand() and, if needed, doInit(parse command line parameters)
+ * !!! Edit carefully, value of 'DEFAULT_BREAKPOINT_LINE' is hardcoded !!!
+ */
+public class AbstractDebuggeeTest {
+    protected DebugeeArgumentHandler argHandler;
+
+    protected IOPipe pipe;
+
+    protected Log log;
+
+    protected boolean callExit = true;
+
+    private boolean success = true;
+
+    protected void setSuccess(boolean value) {
+        success = value;
+    }
+
+    public boolean getSuccess() {
+        return success;
+    }
+
+    public final static int DEFAULT_BREAKPOINT_LINE = 63;
+
+    public final static String DEFAULT_BREAKPOINT_METHOD_NAME = "breakpointMethod";
+
+    public void breakpointMethod() {
+        log.display("In breakpoint method: 'AbstractDebuggeeTest.breakpointMethod()'"); // DEFAULT_BREAKPOINT_LINE
+    }
+
+    protected Map<String, ClassUnloader> loadedClasses = new TreeMap<String, ClassUnloader>();
+
+    public final static String COMMAND_FORCE_BREAKPOINT = "forceBreakpoint";
+
+    //load class with given name with possibility to unload it
+    static public final String COMMAND_LOAD_CLASS = "loadClass";
+
+    // unload class with given name(it is possible for classes loaded via loadTestClass method)
+    // command:className[:<unloadResult>], <unloadResult> - one of UNLOAD_RESULT_TRUE or UNLOAD_RESULT_FALSE
+    static public final String COMMAND_UNLOAD_CLASS = "unloadClass";
+
+    // Optional arguments of COMMAND_UNLOAD_CLASS
+    // (is after unloading class should be really unloaded, default value is UNLOAD_RESULT_TRUE)
+    static public final String UNLOAD_RESULT_TRUE = "unloadResultTrue";
+
+    static public final String UNLOAD_RESULT_FALSE = "unloadResultFalse";
+
+    static public final String COMMAND_CREATE_STATETESTTHREAD = "createStateTestThread";
+
+    static public final String COMMAND_NEXTSTATE_STATETESTTHREAD = "stateTestThreadNextState";
+
+    //force GC using AbstractDebuggeeTest.eatMemory()
+    static public final String COMMAND_FORCE_GC = "forceGC";
+    // GCcount is used to get information about GC activity during test
+    static public final String COMMAND_GC_COUNT = "GCcount";
+    private int lastGCCount;
+
+
+    static public final String stateTestThreadName = "stateTestThread";
+
+    static public final String stateTestThreadClassName = StateTestThread.class.getName();
+
+    // path to classes intended for loading/unloading
+    protected String classpath;
+
+    // classloader loads only test classes from nsk.*
+    public static class TestClassLoader extends CustomClassLoader {
+        public Class<?> loadClass(String name) throws ClassNotFoundException {
+            if (name.startsWith("nsk."))
+                return findClass(name);
+            else
+                return super.loadClass(name);
+        }
+    }
+
+    protected StressOptions stressOptions;
+    protected Stresser stresser;
+
+    // initialize test and remove unsupported by nsk.share.jdi.ArgumentHandler arguments
+    // (ArgumentHandler constructor throws BadOption exception if command line contains unrecognized by ArgumentHandler options)
+    // support -testClassPath parameter: path to find classes for custom classloader
+    protected String[] doInit(String[] args) {
+        stressOptions = new StressOptions(args);
+        stresser = new Stresser(stressOptions);
+
+        ArrayList<String> standardArgs = new ArrayList<String>();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-testClassPath") && (i < args.length - 1)) {
+                classpath = args[i + 1];
+                i++;
+            } else
+                standardArgs.add(args[i]);
+        }
+
+        return standardArgs.toArray(new String[] {});
+    }
+
+    public void loadTestClass(String className) {
+        if (classpath == null) {
+            throw new TestBug("Debuggee requires 'testClassPath' parameter");
+        }
+
+        try {
+            ClassUnloader classUnloader = new ClassUnloader();
+
+            classUnloader.setClassLoader(new TestClassLoader());
+            classUnloader.loadClass(className, classpath);
+            loadedClasses.put(className, classUnloader);
+        } catch (ClassNotFoundException e) {
+            log.complain("Unexpected 'ClassNotFoundException' on loading of the requested class(" + className + ")");
+            e.printStackTrace(log.getOutStream());
+            throw new TestBug("Unexpected 'ClassNotFoundException' on loading of the requested class(" + className + ")");
+        }
+    }
+
+    public static final int MAX_UNLOAD_ATTEMPS = 5;
+
+    public void unloadTestClass(String className, boolean expectedUnloadingResult) {
+        ClassUnloader classUnloader = loadedClasses.get(className);
+
+        int unloadAttemps = 0;
+
+        if (classUnloader != null) {
+            boolean wasUnloaded = false;
+
+            while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) {
+                wasUnloaded = classUnloader.unloadClass();
+            }
+
+            if (wasUnloaded)
+                loadedClasses.remove(className);
+            else {
+                log.display("Class " + className + " was not unloaded");
+            }
+
+            if (wasUnloaded != expectedUnloadingResult) {
+                setSuccess(false);
+
+                if (wasUnloaded)
+                    log.complain("Class " + className + " was unloaded!");
+                else
+                    log.complain("Class " + className + " wasn't unloaded!");
+            }
+        } else {
+            log.complain("Invalid command 'unloadClass' is requested: class " + className + " was not loaded via ClassUnloader");
+            throw new TestBug("Invalid command 'unloadClass' is requested: class " + className + " was not loaded via ClassUnloader");
+        }
+    }
+
+    static public void sleep1sec() {
+        try {
+            Thread.sleep(1000);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private StateTestThread stateTestThread;
+
+    public static final String COMMAND_QUIT = "quit";
+
+    public static final String COMMAND_READY = "ready";
+
+    private void createStateTestThread() {
+        if (stateTestThread != null)
+            throw new TestBug("StateTestThread already created");
+
+        stateTestThread = new StateTestThread(stateTestThreadName);
+    }
+
+    private void stateTestThreadNextState() {
+        if (stateTestThread == null)
+            throw new TestBug("StateTestThread not created");
+
+        stateTestThread.nextState();
+    }
+
+    public boolean parseCommand(String command) {
+        try {
+            StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(command));
+            tokenizer.whitespaceChars(':', ':');
+            tokenizer.wordChars('_', '_');
+            tokenizer.wordChars('$', '$');
+            tokenizer.wordChars('[', ']');
+
+            if (command.equals(COMMAND_FORCE_GC)) {
+                forceGC();
+                lastGCCount = getCurrentGCCount();
+                return true;
+            } else if (command.equals(COMMAND_GC_COUNT)) {
+                pipe.println(COMMAND_GC_COUNT + ":" + (getCurrentGCCount() - lastGCCount));
+                return true;
+            }   else if (command.equals(COMMAND_FORCE_BREAKPOINT)) {
+                breakpointMethod();
+                return true;
+            } else if (command.equals(COMMAND_CREATE_STATETESTTHREAD)) {
+                createStateTestThread();
+
+                return true;
+            } else if (command.equals(COMMAND_NEXTSTATE_STATETESTTHREAD)) {
+                stateTestThreadNextState();
+
+                return true;
+            } else if (command.startsWith(COMMAND_LOAD_CLASS)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                loadTestClass(className);
+
+                return true;
+            } else if (command.startsWith(COMMAND_UNLOAD_CLASS)) {
+                tokenizer.nextToken();
+
+                if (tokenizer.nextToken() != StreamTokenizer.TT_WORD)
+                    throw new TestBug("Invalid command format: " + command);
+
+                String className = tokenizer.sval;
+
+                boolean expectedUnloadingResult = true;
+
+                if (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
+                    if (tokenizer.sval.equals(UNLOAD_RESULT_TRUE))
+                        expectedUnloadingResult = true;
+                    else if (tokenizer.sval.equals(UNLOAD_RESULT_FALSE))
+                        expectedUnloadingResult = false;
+                    else
+                        throw new TestBug("Invalid command format: " + command);
+                }
+
+                unloadTestClass(className, expectedUnloadingResult);
+
+                return true;
+            }
+        } catch (IOException e) {
+            throw new TestBug("Invalid command format: " + command);
+        }
+
+        return false;
+    }
+
+    protected DebugeeArgumentHandler createArgumentHandler(String args[]) {
+        return new DebugeeArgumentHandler(args);
+    }
+
+    protected void init(String args[]) {
+        argHandler = createArgumentHandler(doInit(args));
+        pipe = argHandler.createDebugeeIOPipe();
+        log = argHandler.createDebugeeLog();
+        lastGCCount = getCurrentGCCount();
+    }
+
+    public void initDebuggee(DebugeeArgumentHandler argHandler, Log log, IOPipe pipe, String[] args, boolean callExit) {
+        this.argHandler = argHandler;
+        this.log = log;
+        this.pipe = pipe;
+        this.callExit = callExit;
+        doInit(args);
+    }
+
+    public void doTest(String args[]) {
+        init(args);
+        doTest();
+    }
+
+    public void doTest() {
+        do {
+            log.display("Debuggee " + getClass().getName() + " : sending the command: " + AbstractDebuggeeTest.COMMAND_READY);
+            pipe.println(AbstractDebuggeeTest.COMMAND_READY);
+
+            String command = pipe.readln();
+            log.display("Debuggee: received the command: " + command);
+
+            if (command.equals(AbstractDebuggeeTest.COMMAND_QUIT)) {
+                break;
+            } else {
+                try {
+                    if (!parseCommand(command)) {
+                        log.complain("TEST BUG: unknown debugger command: " + command);
+                        System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                    }
+                } catch (Throwable t) {
+                    log.complain("Unexpected exception in debuggee: " + t);
+                    t.printStackTrace(log.getOutStream());
+                    System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+                }
+            }
+        } while (true);
+
+        log.display("Debuggee: exiting");
+
+        if (callExit) {
+            if (success)
+                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);
+            else
+                System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+    }
+
+    public static void eatMemory() {
+        Runtime runtime = Runtime.getRuntime();
+        long maxMemory = runtime.maxMemory();
+        int memoryChunk = (int) (maxMemory / 50);
+        try {
+            List<Object> list = new ArrayList<Object>();
+            while (true) {
+                list.add(new byte[memoryChunk]);
+            }
+        } catch (OutOfMemoryError e) {
+            // expected exception
+        }
+    }
+
+    public static int getCurrentGCCount() {
+        int result = 0;
+        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
+        for (GarbageCollectorMXBean bean : gcBeans) {
+            result += bean.getCollectionCount();
+        }
+        return result;
+    }
+
+    public void forceGC() {
+        eatMemory();
+    }
+
+    public void voidValueMethod() {
+    }
+
+    public void unexpectedException(Throwable t) {
+        setSuccess(false);
+        t.printStackTrace(log.getOutStream());
+        log.complain("Unexpected exception: " + t);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,1888 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import nsk.share.*;
+import nsk.share.jpda.*;
+
+/**
+ * <code>BindServer</code> is an utility to perform JPDA tests
+ * in remote mode across network.
+ * <p>
+ * This utility should be started on remote host. It listens for connection
+ * from JPDA tests and launches debuggee VM on this host.
+ * <p>
+ * <code>BindServer</code> works together with <code>Binder</code> used in
+ * the tests to incapsulate actions required for launching debuggee VM.
+ * See <code>ProcessBinder</code> and <code>DebugeeArgumentHandler</code>
+ * to know how run tests in local or remote mode across network or
+ * on an single host.
+ * <p>
+ * <code>BindServer</code> is started on the debuggee host.
+ * It recognizes following command line options:
+ * <ul>
+ *   <li><code>-bind.file=<i>filename</i></code> - configuration file
+ *   <li><code>-verbose</code> - print verbose messages
+ * </ul>
+ * <p>
+ * Only required option is <code>-bind.file</code>, which points to the file
+ * where pairs of particular pathes are presented as they are seen from
+ * both hosts along with some other <code>BindServer</code> options.
+ * See <i>execution.html</i> to read more about format of bind-file.
+ *
+ * @see DebugeeBinder
+ * @see DebugeeArgumentHandler
+ */
+public class BindServer implements Finalizable {
+
+    /** Version of <code>BindServer</code> implementation. */
+    public static final long VERSION = 2;
+
+    /** Timeout in milliseconds used for waiting for inner threads. */
+    private static long THREAD_TIMEOUT = DebugeeBinder.THREAD_TIMEOUT;      // milliseconds
+
+    private static int PASSED = 0;
+    private static int FAILED = 2;
+    private static int JCK_BASE = 95;
+
+    private static int TRACE_LEVEL_PACKETS = 10;
+    private static int TRACE_LEVEL_THREADS = 20;
+    private static int TRACE_LEVEL_ACTIONS = 30;
+    private static int TRACE_LEVEL_SOCKETS = 40;
+    private static int TRACE_LEVEL_IO = 50;
+
+    private static String pathSeparator = System.getProperty("path.separator");
+    private static String fileSeparator = System.getProperty("file.separator");
+
+    private static char pathSeparatorChar = pathSeparator.charAt(0);
+    private static char fileSeparatorChar = fileSeparator.charAt(0);
+
+    private static Log log = null;
+    private static Log.Logger logger = null;
+    private static ArgumentHandler argHandler = null;
+
+    private static String pathConvertions[][] = null;
+
+    private ListeningThread listeningThread = null;
+
+    private int totalRequests = 0;
+    private int acceptedRequests = 0;
+    private int unauthorizedRequests = 0;
+    private int busyRequests = 0;
+
+    /**
+     * Start <code>BindServer</code> utility from command line.
+     * This method invokes <code>run()</code> and redirects output
+     * to <code>System.err</code>.
+     *
+     * @param argv list of command line arguments
+     */
+    public static void main (String argv[]) {
+        System.exit(run(argv,System.err) + JCK_BASE);
+    }
+
+    /**
+     * Start <code>BindServer</code> utility from JCK-compatible
+     * environment.
+     *
+     * @param argv list of command line arguments
+     * @param out outpur stream for log messages
+     *
+     * @return FAILED if error occured
+     *         PASSED oterwise
+     */
+    public static int run(String argv[], PrintStream out) {
+        return new BindServer().runIt(argv, out);
+    }
+
+    /**
+     * Perform execution of <code>BindServer</code>.
+     * This method handles command line arguments, starts seperate
+     * thread for listening connection from test on remote host,
+     * and waits for command "exit" from a user.
+     * Finally it closes all conections and prints connections
+     * statiscs.
+     *
+     * @param argv list of command line arguments
+     * @param out outpur stream for log messages
+     *
+     * @return FAILED if error occured
+     *         PASSED oterwise
+     */
+    private int runIt(String argv[], PrintStream out) {
+        try {
+            argHandler = new ArgumentHandler(argv);
+        } catch (ArgumentHandler.BadOption e) {
+            out.println("ERROR: " + e.getMessage());
+            return FAILED;
+        }
+
+        if (argHandler.getArguments().length > 0) {
+            out.println("ERROR: " + "Too many positional arguments in command line");
+            return FAILED;
+        }
+
+        log = new Log(out, argHandler);
+        log.enableErrorsSummary(false);
+        log.enableVerboseOnError(false);
+        logger = new Log.Logger(log, "");
+
+        Finalizer bindFinalizer = new Finalizer(this);
+        bindFinalizer.activate();
+
+        logger.trace(TRACE_LEVEL_THREADS, "BindServer: starting main thread");
+
+        logger.display("Listening to port: " + argHandler.getBindPortNumber());
+        logger.display("Authorizing host: " + argHandler.getDebuggerHost());
+
+        pathConvertions = new String[][] {
+            { "TESTED_JAVA_HOME", argHandler.getDebuggerJavaHome(), argHandler.getDebugeeJavaHome() },
+            { "TESTBASE", argHandler.getDebuggerTestbase(), argHandler.getDebugeeTestbase() },
+            { "WORKDIR", argHandler.getDebuggerWorkDir(), argHandler.getDebugeeWorkDir() }
+        };
+
+        logger.display("Translating pathes:");
+        for (int i = 0; i < pathConvertions.length; i++) {
+            logger.display(pathConvertions[i][0] + ":" +"\n"
+                         + "  " + pathConvertions[i][1] + "\n"
+                         + "  =>" + "\n"
+                         + "  " + pathConvertions[i][2]);
+        }
+
+        String windir = argHandler.getDebugeeWinDir();
+        if (!(windir == null || windir.equals(""))) {
+            logger.display("Using WINDIR: \n"
+                         + "  " + argHandler.getDebugeeWinDir());
+        }
+
+        BufferedReader stdIn = new BufferedReader(
+            new InputStreamReader(System.in));
+
+        listeningThread = new ListeningThread(this);
+        listeningThread.bind();
+        listeningThread.start();
+
+        System.out.println("\n"
+                          + "BindServer started" + "\n"
+                          + "Type \"exit\" to shut down BindServer"
+                          + "\n");
+
+        for (;;) {
+            try {
+                String userInput = stdIn.readLine();
+                if (userInput == null || userInput.equals("exit")
+                        || userInput.equals("quit")) {
+                    logger.display("Shutting down BindServer");
+                    stdIn.close();
+                    stdIn = null;
+                    break;
+                } else if (userInput.trim().equals("")) {
+                    continue;
+                } else {
+                    System.out.println("ERROR: Unknown command: " + userInput);
+                }
+            } catch(IOException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new Failure("Caught exception while reading console command:\n\t"
+                                    + e);
+            }
+        }
+
+        printSummary(System.out);
+
+        logger.trace(TRACE_LEVEL_THREADS, "BindServer: exiting main thread");
+        try {
+            finalize();
+        } catch (Throwable e) {
+            e.printStackTrace(log.getOutStream());
+            logger.complain("Caught exception while finalization of BindServer:\n\t" + e);
+        }
+
+        return PASSED;
+    }
+
+    /**
+     * Print usefull summary statistics about connections occured.
+     *
+     * @param out output stream for printing statistics
+     */
+    private void printSummary(PrintStream out) {
+        out.println("\n"
+                + "Connections summary:" + "\n"
+                + "  Tolal connections:     " + totalRequests + "\n"
+                + "  Accepted authorized:   " + acceptedRequests + "\n"
+                + "  Rejected unauthorized  " + unauthorizedRequests + "\n"
+                + "  Rejected being busy:   " + busyRequests + "\n");
+    };
+
+    /**
+     * Check if given <code>path</code> starts with the specified prefix taking
+     * into account difference between <code>slashChar<code> used in <code>path</code>
+     * and <code>fileSeparatorChar</code> used in <code>prefix</code>.
+     *
+     * @param path path to check
+     * @param prefix prefix to compare with
+     * @param slashChar file separator used in <code>path</code>
+     */
+    private static boolean checkPathPrefix(String path, String prefix, char slashChar) {
+        int prefixLength = prefix.length();
+        if (prefixLength > path.length()) {
+            return false;
+        }
+        for (int i = 0; i < prefixLength; i++) {
+            char pathChar = path.charAt(i);
+            char prefixChar = prefix.charAt(i);
+
+            if (pathChar != prefixChar) {
+                if ((pathChar == slashChar || pathChar == fileSeparatorChar
+                         || pathChar == '\\' || pathChar == '/')
+                    && (prefixChar == slashChar || prefixChar == fileSeparatorChar
+                         || prefixChar == '\\' || prefixChar == '/')) {
+                    // do nothing
+                } else {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Convert given path according to list of prefixes from
+     * <code>pathConvertions</code> table.
+     *
+     * @param path path for converting
+     * @param slash file separator used in <code>path</code>
+     * @param name path identifier used for error messages
+     * @param strict force throwing Failure if path is not matched
+     *
+     * @return string with the converted path
+     *
+     * @throws Failure if path does not matched for translation
+     */
+    private static String convertPath(String path, String slash, String name, boolean strict) {
+        if (path == null)
+            return null;
+
+        char slashChar = slash.charAt(0);
+
+        for (int i = 0; i < pathConvertions.length; i++) {
+            String from = pathConvertions[i][1];
+            String to = pathConvertions[i][2];
+            if (checkPathPrefix(path, from, slashChar)) {
+                return (to + path.substring(from.length())).replace(slashChar, fileSeparatorChar);
+            }
+        }
+        if (strict) {
+            throw new Failure("Path not matched for translation " + name + ":\n\t" + path);
+        }
+        return path;
+    }
+
+    /**
+     * Convert given list of pathes according to list of prefixes from
+     * <code>pathConvertions</code> table by invoking <code>convertPath()</code>
+     * for each path from the list.
+     *
+     * @param list list of pathes for converting
+     * @param slash file separator used in pathes
+     * @param name path identifier used for error messages
+     * @param strict force throwing Failure if some path is not matched
+     *
+     * @return list of strings with converted pathes
+     *
+     * @throws Failure if some path does not matched for translation
+     *
+     * @see #convertPath()
+     */
+    private static String[] convertPathes(String[] list, String slash, String name, boolean strict) {
+        String[] converted = new String[list.length];
+        for (int i = 0; i < list.length; i++) {
+            converted[i] = convertPath(list[i], slash, name, strict);
+        }
+        return converted;
+    }
+
+    /**
+     * Pause current thread for specified amount of time in milliseconds,
+     * This method uses <code>Object.wait(long)</code> method as a reliable
+     * method which prevents whole VM from suspending.
+     *
+     * @param millisecs - amount of time in milliseconds
+     */
+    private static void sleeping(int millisecs) {
+        Object obj = new Object();
+
+        synchronized(obj) {
+            try {
+                obj.wait(millisecs);
+            } catch (InterruptedException e) {
+                e.printStackTrace(log.getOutStream());
+                new Failure("Thread interrupted while sleeping:\n\t" + e);
+            }
+        }
+    }
+
+    /**
+     * Wait for given thread finished for specified timeout or
+     * interrupt this thread if not finished.
+     *
+     * @param thr thread to wait for
+     * @param millisecs timeout in milliseconds
+     */
+    private static void waitInterruptThread(Thread thr, long millisecs) {
+        if (thr != null) {
+            String name = thr.getName();
+            try {
+                if (thr.isAlive()) {
+                    logger.trace(TRACE_LEVEL_THREADS, "Waiting for thread: " + name);
+                    thr.join(millisecs);
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new Failure ("Thread interrupted while waiting for another thread:\n\t"
+                                     + e);
+            } finally {
+                if (thr.isAlive()) {
+                    logger.trace(TRACE_LEVEL_THREADS, "Interrupting not finished thread: " + name);
+                    thr.interrupt();
+/*
+                    logger.display("Stopping not finished thread: " + thr);
+                    thr.stop();
+ */
+                }
+            }
+        }
+    }
+
+    /**
+     * Wait for given thread finished for default timeout
+     * <code>THREAD_TIMEOUT</code> and
+     * interrupt this thread if not finished.
+     *
+     * @param thr thread to wait for
+     */
+    private static void waitInterruptThread(Thread thr) {
+        waitInterruptThread(thr, THREAD_TIMEOUT);
+    }
+
+    /**
+     * Close <code>BindServer</code> by finishing all threads and closing
+     * all conections.
+     */
+    public synchronized void close() {
+        if (listeningThread != null) {
+            listeningThread.close();
+            listeningThread = null;
+        }
+    }
+
+    /**
+     * Make finalization of <code>BindServer</code> object by invoking
+     * method <code>close()</code>.
+     *
+     * @see #close()
+     */
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+
+    /**
+     * Make finalization of <code>BindServer</code> object at program exit
+     * by invoking method <code>finalize()</code>.
+     *
+     * @see #finalize()
+     */
+    public void finalizeAtExit() throws Throwable {
+        finalize();
+        logger.trace(TRACE_LEVEL_THREADS, "BindServer: finalization at exit completed");
+    }
+
+///////// Thread listening a TCP/IP socket //////////
+
+    /**
+     * An inner thread used for listening connection from remote test
+     * and starting separate serving thread for each accepted connection.
+     *
+     * @see ServingThread
+     */
+    private static class ListeningThread extends Thread {
+        private volatile boolean shouldStop = false;
+        private volatile boolean closed = false;
+
+        private BindServer owner = null;
+        private volatile ServingThread servingThread = null;
+        private volatile int taskCount = 0;
+
+        private ObjectOutputStream socOut = null;
+        private ObjectInputStream socIn = null;
+
+        private String autorizedHostName = argHandler.getDebuggerHost();
+        private InetAddress autorizedInetAddresses[] = null;
+        private int port = argHandler.getBindPortNumber();
+        private Socket socket = null;
+        private ServerSocket serverSocket = null;
+        private InetAddress clientInetAddr = null;
+        private String clientHostName = null;
+        private SocketConnection connection = null;
+
+        /**
+         * Make listening thread for given <code>BindServer</code> object
+         * as an owner and bind it to listening port by invoking method
+         * <code>bind()</code>.
+         *
+         * @see bind()
+         */
+        public ListeningThread(BindServer owner) {
+            super("ListeningThread");
+            this.owner = owner;
+            try {
+                autorizedInetAddresses = InetAddress.getAllByName(autorizedHostName);
+            } catch (UnknownHostException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new Failure("Cannot resolve DEBUGGER_HOST value: " + autorizedHostName);
+            }
+        }
+
+        /**
+         * Bind ServerSocket to the specified port.
+         */
+        public void bind() {
+            for (int i = 0; !shouldStop && i < DebugeeBinder.CONNECT_TRIES; i++) {
+                try {
+                    logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: binding to server socket ...");
+                    // length of the queue = 2
+                    serverSocket = new ServerSocket(port, 2);
+                    // timeout for the ServerSocket.accept()
+                    serverSocket.setSoTimeout(DebugeeBinder.CONNECT_TRY_DELAY);
+                    logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: socket bound: " + serverSocket);
+                    logger.display("Bound to listening port");
+                    return;
+                } catch (BindException e) {
+                    logger.display("Socket binding try #" + i + " failed:\n\t" + e);
+                    sleeping(DebugeeBinder.CONNECT_TRY_DELAY);
+                } catch (IOException e) {
+                    e.printStackTrace(log.getOutStream());
+                    throw new Failure("Caught exception while binding to socket:\n\t"
+                                    + e);
+                }
+            }
+            throw new Failure("Unable to bind to socket after "
+                + DebugeeBinder.CONNECT_TRIES + " tries");
+        }
+
+        /**
+         * Accept socket connection from authorized remote host and
+         * start separate <code>SrvingThread</code> to handle each connection.
+         * Connection from unauthorized hosts or connections made while
+         * current connection is alive are rejected.
+         *
+         * @see ServingThread
+         * @see #llowConnection()
+         * @see allowServing()
+         */
+        public void run() {
+            String reply = null;
+
+            logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: started");
+            logger.display("Listening for connection from remote host");
+            while(!(shouldStop || isInterrupted())) {
+                try {
+                    try {
+                        logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: waiting for connection from test");
+                        socket = serverSocket.accept();
+                        logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: connection accepted");
+                    } catch(InterruptedIOException e) {
+//                        logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: timeout of waiting for connection from test");
+                        continue;
+                    }
+                    owner.totalRequests++;
+                    logger.display("");
+                    clientInetAddr = socket.getInetAddress();
+                    clientHostName = clientInetAddr.getHostName();
+                    logger.display("Connection #" + owner.totalRequests
+                                    + " requested from host: " + clientHostName);
+                    connection = new SocketConnection(logger, "BindServer");
+//                    connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT);
+                    connection.setSocket(socket);
+                    socket = null;
+                    if (allowConnection()) {
+                        if (allowServing()) {
+                            owner.acceptedRequests++;
+                            reply = "host authorized: " + clientHostName;
+                            logger.display("Accepting connection #" + owner.acceptedRequests
+                                            + ": " + reply);
+                            servingThread = new ServingThread(this, connection);
+                            servingThread.start();
+                            cleanHostConnection();
+                        } else {
+                            owner.busyRequests++;
+                            reply = "BindServer is busy";
+                            logger.complain("Rejecting connection #" + owner.busyRequests
+                                            + ": " + reply);
+                            connection.writeObject(new RequestFailed(reply));
+                            closeHostConnection();
+                        }
+                    } else {
+                        owner.unauthorizedRequests++;
+                        reply = "host unauthorized: " + clientHostName;
+                        logger.complain("Rejecting connection #" + owner.unauthorizedRequests
+                                            + ": " + reply);
+                        connection.writeObject(new RequestFailed(reply));
+                        closeHostConnection();
+                    }
+                } catch (Exception e) {
+                    logger.complain("Caught exception while accepting connection:\n" + e);
+                    e.printStackTrace(log.getOutStream());
+                }
+            }
+            logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: exiting");
+            closeConnection();
+        }
+
+        /**
+         * Check if the connection made is from authorized host.
+         *
+         * @return true if connection is allowed because host authorized
+         *         false if connection is rejected because host unauthorized
+         */
+        private boolean allowConnection() {
+            // check if local host from loopback address
+            if (autorizedHostName.equals("localhost"))
+                return clientInetAddr.isLoopbackAddress();
+
+            // check if equal hostname
+            if (autorizedHostName.equals(clientHostName))
+                return true;
+
+            // check if equal host address
+            for (int i = 0; i < autorizedInetAddresses.length; i++) {
+                if (clientInetAddr.equals(autorizedInetAddresses[i])) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /**
+         * Check if no current connection exists or it is dead.
+         * If current connection presents it will be tested by pinging
+         * remote host and aborted if host sends no reply. If an alive
+         * connection exists, new connection will be rejected.
+         *
+         * @return true if no alive connection exists
+         *         false otherwise
+         */
+        private boolean allowServing() {
+            if (servingThread == null) {
+                return true;
+            }
+            if (servingThread.done) {
+                return true;
+            }
+            if (!servingThread.isConnectionAlive()) {
+                logger.display("# WARNING: Previous connection from remote host is dead: aborting connection");
+                servingThread.close();
+                servingThread = null;
+                return true;
+            }
+
+/*
+            logger.complain("Previous connection from remote host is alive: starting new connection");
+            servingThread = null;
+            return true;
+ */
+            logger.complain("Previous connection from remote host is alive: reject new connection");
+            return false;
+        }
+
+        /**
+         * Wait for this thread finished
+         * for specified timeout or interrupt it.
+         *
+         * @param millis timeout in milliseconds
+         */
+        public void waitForThread(long millis) {
+            shouldStop = true;
+            waitInterruptThread(this, millis);
+        }
+
+        /**
+         * Close socket connection from remote host.
+         */
+        private void closeHostConnection() {
+            if (connection != null) {
+                connection.close();
+            }
+            if (socket != null) {
+                try {
+                    socket.close();
+                } catch (IOException e) {
+                    logger.complain("Caught IOException while closing socket:\n\t"
+                                    + e);
+                }
+                socket = null;
+            }
+        }
+
+        /**
+         * Assign <null> to connection and socket objects
+         * but do not close them.
+         */
+        private void cleanHostConnection() {
+            connection = null;
+            socket = null;
+        }
+
+        /**
+         * Close all connections and sockets.
+         */
+        private void closeConnection() {
+            closeHostConnection();
+            if (serverSocket != null) {
+                try {
+                    serverSocket.close();
+                } catch (IOException e) {
+                    logger.complain("Caught IOException while closing ServerSocket:\n\t"
+                                    + e);
+                }
+                serverSocket = null;
+            }
+        }
+
+        /**
+         * Close thread by closing all connections and waiting
+         * foor thread finished.
+         *
+         * @see #closeConnection()
+         */
+        public synchronized void close() {
+            if (closed) {
+                return;
+            }
+            closeHostConnection();
+            if (servingThread != null) {
+                servingThread.close();
+                servingThread = null;
+            }
+            waitForThread(THREAD_TIMEOUT);
+            closeConnection();
+            closed = true;
+            logger.trace(TRACE_LEVEL_THREADS, "ListeningThread closed");
+        }
+
+    } // ListeningThread
+
+///////// Thread working with a communication channel //////////
+
+    /**
+     * An internal thread for handling each connection from a test
+     * on remote host. It reads requests from test and starts separate
+     * <code>LaunchingThread</code> to execute each request.
+     *
+     * @see LaunchingThread
+     */
+    private static class ServingThread extends Thread {
+        private volatile boolean shouldStop = false;
+        private volatile boolean closed = false;
+        private volatile boolean done = false;
+
+        private ListeningThread owner = null;
+        private LaunchingThread launchingThread = null;
+
+        private SocketConnection connection = null;
+
+        /**
+         * Make serving thread with specified input/output connection streams
+         * and given <code>Listenerthread</code> as an owner.
+         *
+         * @param owner owner of this thread
+         * @param connection established socket connection with test
+         */
+        public ServingThread(ListeningThread owner, SocketConnection connection) {
+            super("ServingThread");
+            this.owner = owner;
+            this.connection = connection;
+        }
+
+        /**
+         * Read requests from socket connection and start <code>LaunchingThread</code>
+         * to perform each requested action.
+         */
+        public void run() {
+            logger.trace(TRACE_LEVEL_THREADS, "ServingThread: starting handling requests from debugger");
+            try {
+                // sending OK(version)
+                logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: sending initial OK(VERSION) to debugger");
+                connection.writeObject(new OK(VERSION));
+
+                // receiving TaskID(id)
+                logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for TaskID from debugger");
+                Object taskID = connection.readObject();
+                logger.trace(TRACE_LEVEL_IO, "ServingThread: received TaskID from debugger: " + taskID);
+                if (taskID instanceof TaskID) {
+                    String id = ((TaskID)taskID).id;
+                    owner.taskCount++;
+                    logger.println("[" + owner.taskCount + "/" + owner.owner.totalRequests + "]: " + id);
+                } else {
+                    throw new Failure("Unexpected TaskID received form debugger: " + taskID);
+                }
+
+                // starting launching thread
+                launchingThread = new LaunchingThread(this, connection);
+                launchingThread.start();
+
+                // receiving and handling requests
+                while(!(shouldStop || isInterrupted())) {
+                    logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for request from debugger");
+                    Object request = connection.readObject();
+                    logger.trace(TRACE_LEVEL_IO, "ServingThread: received request from debugger: " + request);
+                    if (request == null) {
+                        logger.display("Connection closed");
+                        break;
+                    } else if (request instanceof Disconnect) {
+                        logger.display("Closing connection by request");
+                        request = null;
+                        break;
+                    } else {
+                        boolean success = false;
+                        long timeToFinish = System.currentTimeMillis() + THREAD_TIMEOUT;
+                        while (System.currentTimeMillis() < timeToFinish) {
+                            if (launchingThread.doneRequest()) {
+                                success = true;
+                                logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: asking launching thread to handle request: " + request);
+                                launchingThread.handleRequest(request);
+                                break;
+                            }
+                            try {
+                                launchingThread.join(DebugeeBinder.TRY_DELAY);
+                            } catch (InterruptedException e) {
+                                throw new Failure("ServingThread interrupted while waiting for LaunchingThread:\n\t"
+                                                + e);
+                            }
+                        }
+                        if (!success) {
+                            logger.complain("Rejecting request because of being busy:\n" + request);
+                            connection.writeObject(
+                                new RequestFailed("Busy with handling previous request"));
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace(log.getOutStream());
+                logger.complain("Caught exception while handling request:\n\t" + e);
+            } finally {
+                logger.trace(TRACE_LEVEL_THREADS, "ServingThread: exiting");
+                closeConnection();
+                done = true;
+            }
+        }
+
+        /**
+         * Check if present socket connection is alive.
+         */
+        private boolean isConnectionAlive() {
+            return (connection != null && connection.isConnected());
+        }
+
+        /**
+         * Wait for this thread finished
+         * for specified timeout or interrupt it.
+         *
+         * @param millis timeout in milliseconds
+         */
+        public void waitForThread(long millis) {
+            shouldStop = true;
+            waitInterruptThread(this, millis);
+        }
+
+        /**
+         * Close socket connection from remote host.
+         */
+        private void closeConnection() {
+            if (connection != null) {
+                connection.close();
+            }
+            if (launchingThread != null) {
+                launchingThread.handleRequest(null);
+            }
+        }
+
+        /**
+         * Close thread closing socket connection and
+         * waiting for thread finished.
+         */
+        public synchronized void close() {
+            if (closed) {
+                return;
+            }
+            closeConnection();
+            if (launchingThread != null) {
+                launchingThread.close();
+                launchingThread = null;
+            }
+            waitForThread(THREAD_TIMEOUT);
+            closed = true;
+            logger.trace(TRACE_LEVEL_THREADS, "ServingThread closed");
+        }
+
+    } // ServingThread
+
+///////// Thread serving a particular Binder's request //////////
+
+    /**
+     * An internal thread to execute each request from a test on remote host.
+     * Requests are coming from ServingThread by invoking handleRequest(Object)
+     * method.
+     */
+    private static class LaunchingThread extends Thread {
+        private volatile boolean shouldStop = false;
+        private volatile boolean closed = false;
+        public volatile boolean done = false;
+
+        private ServingThread owner = null;
+//        private ProcessWaitingThread waitingThread = null;
+        private Process process = null;
+
+        private StreamRedirectingThread stdoutRedirectingThread = null;
+        private StreamRedirectingThread stderrRedirectingThread = null;
+
+        /** Notification about request occurence. */
+        private volatile Object notification = new Object();
+        /** Request to execute. */
+        private volatile Object request = null;
+        /** Socket stream to send replies to. */
+        private SocketConnection connection = null;
+
+        /**
+         * Make thread for executing requests from a test and
+         * send reply.
+         *
+         * @param owner owner of this thread
+         * @connection socket connection for sending replies
+         */
+        public LaunchingThread(ServingThread owner, SocketConnection connection) {
+            super("LaunchingThread");
+            this.owner = owner;
+            this.connection = connection;
+        }
+
+        /**
+         * Notify this thread that new request has come.
+         *
+         * @param request request to execute
+         */
+        public void handleRequest(Object request) {
+            synchronized (notification) {
+                this.request = request;
+                notification.notifyAll();
+            }
+        }
+
+        /**
+         * Check if request has been executed.
+         */
+        public boolean doneRequest() {
+            return done;
+        }
+
+        /**
+         * Wait for request notification from <code>ServingThread</code>
+         * and execute an action according to the request.
+         * Request <i>null</code> means thread should finish.
+         */
+        public void run() {
+            logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: started to handle request");
+            done = true;
+            while (!isInterrupted()) {
+                // wait for new request notification
+                logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: waiting for request");
+                synchronized (notification) {
+                    try {
+                        notification.wait();
+                    } catch (InterruptedException e) {
+                        logger.complain("LaunchingThread interrupted while waiting for request:\n\t"
+                                        + e);
+                        break;
+                    }
+                }
+
+                // execute the request
+                try {
+                    logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: handling request: " + request);
+                    if (request == null) {
+                        break;
+                    } else if (request instanceof LaunchDebugee) {
+                        launchDebugee((LaunchDebugee)request);
+                    } else if (request instanceof WaitForDebugee) {
+                        waitForDebugee((WaitForDebugee)request);
+                    } else if (request instanceof DebugeeExitCode) {
+                        debugeeExitCode((DebugeeExitCode)request);
+                    } else if (request instanceof KillDebugee) {
+                        killDebugee((KillDebugee)request);
+                    } else {
+                        String reason = "Unknown request: " + request;
+                        logger.complain(reason);
+                        sendReply(new RequestFailed(reason));
+                    }
+                } catch (Exception e) {
+                    e.printStackTrace(log.getOutStream());
+                    logger.complain("Caught exception while handling request:\n\t" + e);
+                }
+                done = true;
+            }
+            done = true;
+            logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: exiting");
+            closeConnection();
+        }
+
+        /**
+         * Send given reply to remote test.
+         *
+         * @param reply reply object to send
+         */
+        public void sendReply(Object reply) throws IOException {
+            connection.writeObject(reply);
+        }
+
+        /**
+         * Send given output line to remote test.
+         *
+         * @param reply wrapper object for output line to send
+         */
+        public void sendStreamMessage(RedirectedStream wrapper) throws IOException {
+            logger.trace(TRACE_LEVEL_ACTIONS, "Sending output line wrapper to debugger: " + wrapper);
+            if (connection.isConnected()) {
+                sendReply(wrapper);
+            } else {
+                logger.complain("NOT redirected: " + wrapper.line);
+            }
+        }
+
+        /**
+         * Launch two <code>StreamRedirectingThread</code> threads to redirect
+         * stdin/stderr output of debuggee VM process via <code>BindServer</code>
+         * connection.
+         *
+         * @param process debuggee VM process
+         */
+        private void launchStreamRedirectors(Process process) {
+            stdoutRedirectingThread =
+                new StdoutRedirectingThread(this, process.getInputStream(),
+                                            DebugeeProcess.DEBUGEE_STDOUT_LOG_PREFIX);
+            stdoutRedirectingThread.start();
+            stderrRedirectingThread =
+                new StderrRedirectingThread(this, process.getErrorStream(),
+                                            DebugeeProcess.DEBUGEE_STDERR_LOG_PREFIX);
+            stderrRedirectingThread.start();
+        }
+
+        /**
+         * Execute request for launching debuggee.
+         *
+         * @param request request to execute
+         */
+        private void launchDebugee(LaunchDebugee request) throws IOException {
+            logger.trace(TRACE_LEVEL_ACTIONS, "LaunchDebugee: handle request: " + request);
+
+            if (process != null) {
+                logger.complain("Unable to launch debuggee: process already launched");
+                sendReply(new RequestFailed("Debuggee process already launched"));
+                return;
+            }
+
+            try {
+                String[] cmd = request.cmd;
+                cmd[0] = convertPath(cmd[0], request.slash, "TESTED_JAVA_HOME", true);
+                for (int i = 1; i < cmd.length; i++) {
+                    cmd[i] = convertPath(cmd[i], request.slash, "JAVA_ARGS", false);
+                }
+                String workDir = convertPath(request.workDir, request.slash, "WORKDIR", true);
+                String[] classPathes = convertPathes(request.classPathes, request.slash, "CLASSPATH", true);
+                String windir = argHandler.getDebugeeWinDir();
+
+                boolean win = (!(windir == null || windir.equals("")));
+                String[] envp = new String[win ? 3 : 1] ;
+                envp[0] = "CLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", pathSeparator);
+                if (win) {
+                    envp[1] = "WINDIR=" + windir;
+                    envp[2] = "SystemRoot=" + windir;
+                }
+
+                logger.display("Setting environment:\n"
+                                + "  " + ArgumentHandler.joinArguments(envp, "", "\n  "));
+                logger.display("Setting work dir:\n"
+                                + "  " + workDir);
+                logger.display("Launching debuggee:\n"
+                                + "  " + ArgumentHandler.joinArguments(cmd, "\""));
+
+                process = Runtime.getRuntime().exec(cmd, envp, new File(workDir));
+                logger.display("  debuggee launched successfully");
+
+                launchStreamRedirectors(process);
+            } catch (Exception e) {
+                if (!(e instanceof Failure)) {
+                    e.printStackTrace(log.getOutStream());
+                }
+                logger.complain("Caught exception while launching debuggee:\n\t" + e);
+                sendReply(new CaughtException(e));
+                return;
+            }
+
+            sendReply(new OK());
+        }
+
+        /**
+         * Execute request for waiting for debuggee exited.
+         *
+         * @param request request to execute
+         */
+        private void waitForDebugee(WaitForDebugee request) throws IOException {
+            logger.trace(TRACE_LEVEL_ACTIONS, "WaitForDebugee: handle request: " + request);
+
+            if (process == null) {
+                String reply = "No debuggee process to wait for";
+                logger.complain(reply);
+                sendReply(new RequestFailed(reply));
+                return;
+            }
+
+            logger.display("Waiting for debuggee to exit");
+/*
+            // because timeout is not supported now
+            // we do not use separate thread for waiting for process
+            // and so following lines are commented out
+
+            waitingThread = new ProcessWaitingThread();
+            logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: starting thread for waiting for debugee process");
+            waitingThread.start();
+            try {
+                waitingThread.join(request.timeout);
+                if (waitingThread.isAlive()) {
+                    String reply = "Timeout exceeded while waiting for debuggee to exit";
+                    logger.complain(reply);
+                    waitingThread.interrupt();
+                    sendReply(socOut, new RequestFailed(reply));
+                    return;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace(log.getOutStream());
+                logger.complain("Caught exception while waiting for debuggee:\n\t" + e);
+                sendReply(new CaughtException(e));
+                return;
+            }
+            int exitStatus = waitingThread.exitStatus;
+            waitingThread = null;
+ */
+            int exitStatus;
+            try {
+                exitStatus = process.waitFor();
+                waitForRedirectors(THREAD_TIMEOUT);
+                process.destroy();
+            } catch (InterruptedException e) {
+                e.printStackTrace(log.getOutStream());
+                logger.complain("Caught exception while waiting for debuggee process to exit:\n\t"
+                                + e);
+                sendReply(new CaughtException(e));
+                return;
+            }
+            logger.display("  debuggee exited with exit status: " + exitStatus);
+            sendReply(new OK(exitStatus));
+        }
+
+        /**
+         * Execute request for returning debuggee exit code.
+         *
+         * @param request request to execute
+         */
+        private void debugeeExitCode(DebugeeExitCode request) throws IOException {
+            logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: handle request: " + request);
+
+            if (process == null) {
+                String reply = "No debuggee process to get exit code for";
+                logger.complain(reply);
+                sendReply(new RequestFailed(reply));
+                return;
+            }
+
+            int exitStatus = 0;
+            try {
+                exitStatus = process.exitValue();
+            } catch (IllegalThreadStateException e) {
+                logger.display("# WARNING: Caught exception while getting exit status of debuggee:\n\t"
+                                + e);
+                sendReply(new CaughtException(e));
+                return;
+            }
+            logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: return debuggee exit status: " + exitStatus);
+            sendReply(new OK(exitStatus));
+        }
+
+        /**
+         * Execute request for unconditional terminating debuggee process.
+         *
+         * @param request request to execute
+         */
+        private void killDebugee(KillDebugee request) throws IOException {
+            logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: handle request: " + request);
+
+            if (process == null) {
+                String reply = "No debuggee process to kill";
+                logger.complain(reply);
+                sendReply(new RequestFailed(reply));
+                return;
+            }
+
+            logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: killing debuggee process");
+            process.destroy();
+
+            logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: debuggee process killed");
+            sendReply(new OK());
+        }
+
+        /**
+         * Terminate debigee VM process if still alive.
+         */
+        private void terminateDebugeeAtExit() {
+            if (process != null) {
+                logger.trace(TRACE_LEVEL_ACTIONS, "Checking that debuggee process has exited correctly");
+                try {
+                    int value = process.exitValue();
+                } catch (IllegalThreadStateException e) {
+                    logger.complain("Debuggee process has not exited correctly: trying to kill it");
+                    process.destroy();
+                    try {
+                        int value = process.exitValue();
+                    } catch (IllegalThreadStateException ie) {
+                        logger.complain("Debuggee process is alive after killing it");
+                    }
+                    process = null;
+                    return;
+                }
+                logger.trace(TRACE_LEVEL_ACTIONS, "Debuggee process has exited correctly");
+            }
+        }
+
+        /**
+         * Wait for stream redirecting threads finished
+         * for specified timeout.
+         *
+         * @param millis timeout in milliseconds
+         */
+        private void waitForRedirectors(long millis) {
+            try {
+                if (stdoutRedirectingThread != null) {
+                    stdoutRedirectingThread.join(millis);
+                }
+                if (stderrRedirectingThread != null) {
+                    stderrRedirectingThread.join(millis);
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace(log.getOutStream());
+                logger.complain("Caught exception while waiting for debuggee process exited:\n\t"
+                                + e);
+            }
+        }
+
+        /**
+         * Wait for this thread finished
+         * for specified timeout or interrupt it.
+         *
+         * @param millis timeout in milliseconds
+         */
+        public void waitForThread(long millis) {
+            shouldStop = true;
+            handleRequest(null);
+            waitInterruptThread(this, millis);
+        }
+
+        /**
+         * Close connection with debuggee.
+         */
+        public void closeConnection() {
+            // no connections to close
+        }
+
+        /**
+         * Close thread by closing all connections with debuggee,
+         * finishing all redirectors and wait for thread finished.
+         */
+        public synchronized void close() {
+            if (closed) {
+                return;
+            }
+            closeConnection();
+            terminateDebugeeAtExit();
+            if (stdoutRedirectingThread != null) {
+                stdoutRedirectingThread.close();
+                stdoutRedirectingThread = null;
+            }
+            if (stderrRedirectingThread != null) {
+                stderrRedirectingThread.close();
+                stderrRedirectingThread = null;
+            }
+            waitForThread(THREAD_TIMEOUT);
+            closed = true;
+            logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread closed");
+        }
+
+        /**
+         * An inner thread for waiting for debuggee process exited
+         * and saving its exit status. (currently not used)
+         */
+/*
+        private class ProcessWaitingThread extends Thread {
+            int exitStatus = 0;
+
+            ProcessWaitingThread() {
+                super("ProcessWaitingThread");
+            }
+
+            public void run() {
+                logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: starting waiting for process");
+                try {
+                    exitStatus = process.waitFor();
+                } catch (InterruptedException e) {
+                    e.printStackTrace(log.getOutStream());
+                    logger.complain("Caught exception while waiting for debuggee process:\n\t"
+                                    + e);
+                }
+                logger.trace(TRACE_LEVEL_ACTIONS, "ProcessWaitingThread: process finished with status: " + exitStatus);
+                logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: exiting");
+            }
+
+            public synchronized void close() {
+                logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread closed");
+            }
+
+        } // ProcessWaitingThread
+ */
+    } // LaunchingThread
+
+///////// Redirecting threads /////////
+
+    /**
+     * An abstract base class for internal threads which redirects stderr/stdout
+     * output from debuggee process via <code>BindServer</code> connection.
+     * <p>
+     * Two derived classes will redirect <i>stderr</i> or </i>stdout</i> stream
+     * by enwrapping stream line by <code>DebugeeStderr</code> or
+     * <code>DebugeeStderr</code> objects. They should implement only one
+     * abstract method <code>enwrapLine(String)</code> to make the difference.
+     */
+    public static abstract class StreamRedirectingThread extends Thread {
+        private volatile boolean shouldStop = false;
+        private volatile boolean closed = false;
+
+        private LaunchingThread owner = null;
+
+        private BufferedReader bin = null;
+        private String prefix = null;
+
+        /**
+         * Make a thread to enwrap and redirect lines from specified
+         * input stream with given prefix.
+         *
+         * @param owner owner of this thread
+         * @param is input stream to redirect lines from
+         * @param prefix prefix to add to each line
+         */
+        public StreamRedirectingThread(LaunchingThread owner, InputStream is, String prefix) {
+            super("StreamRedirectingThread");
+            this.prefix = prefix;
+            this.owner = owner;
+            bin = new BufferedReader(new InputStreamReader(is));
+        }
+
+        /**
+         * Read lines from an input stream, enwrap them, and send to remote
+         * test via <code>BindServer</code> connection.
+         */
+        public void run() {
+            logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: starting redirect output stream");
+            try {
+                String line;
+                logger.trace(TRACE_LEVEL_IO, "StreamRedirectingThread: waiting for line from debuggee output");
+                while(!shouldStop) {
+                    line = bin.readLine();
+                    if (line == null)
+                        break;
+                    owner.sendStreamMessage(enwrapLine(prefix + line));
+                }
+            } catch (EOFException e) {
+                logger.display("Debuggee output stream closed by process");
+            } catch (IOException e) {
+                e.printStackTrace(log.getOutStream());
+                logger.display("# WARNING: Connection to debuggee output stream aborted:\n\t" + e);
+            } catch (Exception e) {
+                e.printStackTrace(log.getOutStream());
+                logger.complain("Caught exception while redirecting debuggee output stream:\n\t"
+                                + e);
+            }
+            logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: exiting");
+            closeConnection();
+        }
+
+        /**
+         * Envrap output line by the appropriate wrapper.
+         * @param line line to enwrap
+         */
+        protected abstract RedirectedStream enwrapLine(String line);
+
+        /**
+         * Wait for this thread finished or interrupt it.
+         *
+         * @param millis timeout in milliseconds
+         */
+        public void waitForThread(long millis) {
+            shouldStop = true;
+            waitInterruptThread(this, millis);
+        }
+
+        /**
+         * Close redirected process output stream.
+         */
+        public void closeConnection() {
+            if (closed) {
+                return;
+            }
+            if (bin != null) {
+                try {
+                    bin.close();
+                } catch (IOException e) {
+                    e.printStackTrace(log.getOutStream());
+                    logger.complain("Caught exception while closing debuggee output stream:\n\t"
+                                    + e);
+                }
+                bin = null;
+            }
+            closed = true;
+            logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed");
+        }
+
+        /**
+         * Close thread by waiting redirected stream closed
+         * and finish the thread.
+         */
+        public synchronized void close() {
+            if (closed) {
+                return;
+            }
+            waitForThread(THREAD_TIMEOUT);
+            closeConnection();
+            closed = true;
+            logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed");
+        }
+
+    } // StreamRedirectingThread
+
+    /**
+     * Particalar case of <code>StreamRedirectingThread</code> to redirect
+     * <i>stderr</i> stream by enwrapping lines into <code>DebugeeStderr</code>
+     * objects.
+     */
+    private static class StderrRedirectingThread extends StreamRedirectingThread {
+
+        /**
+         * Make a thread to redirect <i>stderr</i> output stream.
+         */
+        StderrRedirectingThread(LaunchingThread owner, InputStream is, String prefix) {
+            super(owner, is, prefix);
+            setName("StderrRedirectingThread");
+        }
+
+        /**
+         * Enwrap given line into <code>DebugeeStderr</code> object.
+         */
+        protected RedirectedStream enwrapLine(String line) {
+            return new DebugeeStderr(line);
+        }
+
+    }
+
+    /**
+     * Particalar case of <code>StreamRedirectingThread</code> to redirect
+     * <i>stdout</i> stream by enwrapping lines into <code>DebugeeStdout</code>
+     * objects.
+     */
+    private static class StdoutRedirectingThread extends StreamRedirectingThread {
+
+        /**
+         * Make a thread to redirect <i>stdout</i> output stream.
+         */
+        StdoutRedirectingThread(LaunchingThread owner, InputStream is, String prefix) {
+            super(owner, is, prefix);
+            setName("StdoutRedirectingThread");
+        }
+
+        /**
+         * Enwrap given line into <code>DebugeeStdout</code> object.
+         */
+        protected RedirectedStream enwrapLine(String line) {
+            return new DebugeeStdout(line);
+        }
+
+    }
+
+///////// BinderServer's packets //////////
+
+    /**
+     * Base serializable object to transmit request or reply
+     * via <code>BindServer</code> connection.
+     */
+    public static class Packet implements Serializable {}
+
+    ///////// Binder's requests //////////
+
+    /**
+     * Base class to represent request to <code>BindServer</code>.
+     */
+    public static abstract class Request extends Packet {}
+
+    /**
+     * This class implements task identification command.
+     */
+    public static class TaskID extends Request {
+        public String id;
+
+        public TaskID(String id) {
+            this.id = id;
+        }
+
+        public String toString() {
+            return "TaskID: id=" + id;
+        }
+    }
+
+    /**
+     * This class implements a request for launching a debugee.
+     */
+    public static class LaunchDebugee extends Request {
+        public String slash;         // slash symbol used on debugger host
+        public String[] cmd;         // command line arguments as seen on debugger host
+        public String workDir;       // path to working directory as seen on debugger host
+        public String[] classPathes; // list of class pathes as seen on debugger host
+
+        public LaunchDebugee(String[] cmd, String slash, String workDir,
+                            String[] pathes, String[] classPathes,
+                            String[] libPathes) {
+            this.cmd = cmd;
+            this.slash = slash;
+            this.workDir = workDir;
+            this.classPathes = classPathes;
+        }
+
+        public String toString() {
+            return "LaunchDebugee:"
+                + "\n\tcommand=" + ArgumentParser.joinArguments(cmd, "\"")
+                + "\n\tWORKDIR=" + workDir
+                + "\n\tCLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", ":")
+                + "\n\tslash=" + slash;
+        }
+    }
+
+    /**
+     * This class implements a request for waiting for debugee
+     * termination.
+     */
+    public static class WaitForDebugee extends Request {
+        public long timeout = 0; // timeout in minutes for waiting
+
+        public WaitForDebugee(long value) {
+            timeout = value;
+        }
+
+        public String toString() {
+            return "WaitForDebugee: timeout=" + timeout;
+        }
+    }
+
+    /**
+     * This class implements a request for exit code of
+     * debugee process.
+     */
+    public static class DebugeeExitCode extends Request {
+        public String toString() {
+            return "SebugeeExitCode";
+        }
+    }
+
+    /**
+     * This class implements a request for killing debugee process.
+     */
+    public static class KillDebugee extends Request {
+        public String toString() {
+            return "KillDebugee";
+        }
+    }
+
+    /**
+     * This class implements a request to disconnect connection with test.
+     */
+    public static class Disconnect extends Request {
+        public String toString() {
+            return "Disconnect";
+        }
+    }
+
+    ///////// BindServer's responses //////////
+
+    /**
+     * Base class to represent response from <code>BindServer</code>.
+     */
+    public static abstract class Response extends Packet {}
+
+    /**
+     * This class implements a response that a previoulsy received
+     * request has been successfully performed.
+     */
+    public static class OK extends Response {
+        public long info = BindServer.VERSION; // optional additional info
+
+        public OK() {
+        }
+
+        public OK(long value) {
+            info = value;
+        }
+
+        public String toString() {
+            return "OK(" + info + ")";
+        }
+    }
+
+    /**
+     * This class implements a response that the BindServer is
+     * unable to serve a previoulsy received request.
+     */
+    public static class RequestFailed extends Response {
+        public String reason; // the short explanation of failure
+
+        public RequestFailed(String reason) {
+            this.reason = reason;
+        }
+
+        public String toString() {
+            return "RequestFailed(" + reason + ")";
+        }
+    }
+
+    /**
+     * This class implements a response that the BindServer is
+     * unable to serve a previoulsy received request because of
+     * caught exception.
+     */
+    public static class CaughtException extends RequestFailed {
+        public CaughtException(Exception cause) {
+            super("Caught exception: " + cause);
+        }
+    }
+
+    ///////// Wrappers for redirected messages //////////
+
+    /**
+     * Base class to represent wrappers for redirected streams.
+     */
+    public static class RedirectedStream extends Packet {
+        public String line; // line containing line from redirected stream
+
+        public RedirectedStream(String str) {
+            line = str;
+        }
+
+        public String toString() {
+            return "RedirectedStream(" + line + ")";
+        }
+    }
+
+    /**
+     * This class enwraps redirected line of <i>stdout</i> stream.
+     */
+    public static class DebugeeStdout extends RedirectedStream {
+
+        public DebugeeStdout(String str) {
+            super(str);
+        }
+
+        public String toString() {
+            return "DebugeeStdout(" + line + ")";
+        }
+    }
+
+    /**
+     * This class enwraps redirected line of <i>stderr</i> stream.
+     */
+    public static class DebugeeStderr extends RedirectedStream {
+        public DebugeeStderr(String str) {
+            super(str);
+        }
+
+        public String toString() {
+            return "DebugeeStderr(" + line + ")";
+        }
+    }
+
+/////// ArgumentHandler for BindServer command line /////////
+
+    /**
+     * This class is used to parse arguments from command line
+     * and specified <i>bind-file</i>,
+     */
+    private static class ArgumentHandler extends ArgumentParser {
+
+        protected Properties fileOptions;
+
+        /**
+         * Make parser object for command line arguments.
+         *
+         * @param args list of command line arguments
+         */
+        public ArgumentHandler(String[] args) {
+            super(args);
+        }
+
+        /**
+         * Check if given command line option is aloowed.
+         *
+         * @param option option name
+         * @param value option value
+         */
+        protected boolean checkOption(String option, String value) {
+            if (option.equals("bind.file")) {
+                // accept any file name
+                return true;
+            }
+            return super.checkOption(option, value);
+        }
+
+        /**
+         * Check if all recignized options are compatible.
+         */
+        protected void checkOptions() {
+            if (getBindFileName() == null) {
+                throw new BadOption("Option -bind.file is requred ");
+            }
+            super.checkOptions();
+        }
+
+        /**
+         * Check if value of this option points to a existing directory.
+         *
+         * @param option option name
+         * @param dir option value
+         */
+        private void checkDir(String option, String dir) {
+            File file = new File(dir);
+            if (!file.exists()) {
+                throw new BadOption(option + " does not exist: " + dir);
+            }
+            if (!file.isAbsolute()) {
+                throw new BadOption(option + " is not absolute pathname: " + dir);
+            }
+            if (!file.isDirectory()) {
+                throw new BadOption(option + " is not directory: " + dir);
+            }
+        }
+
+        /**
+         * Check if option from <i>bind-file</i> is allowed.
+         *
+         * @param option option name
+         * @param value option value
+         */
+        protected boolean checkAdditionalOption(String option, String value) {
+
+            if (option.equals("DEBUGGER_HOST")) {
+                // accept any hostname
+                return true;
+            }
+
+            if (option.equals("BINDSERVER_PORT")) {
+                // accept only integer value
+                try {
+                    int port = Integer.parseInt(value);
+                } catch (NumberFormatException e) {
+                    throw new Failure("Not integer value of bind-file option " + option
+                                        + ": " + value);
+                }
+                return true;
+            }
+
+            if (option.equals("DEBUGGER_TESTED_JAVA_HOME")
+                    || option.equals("DEBUGGER_WORKDIR")
+                    || option.equals("DEBUGGER_TESTBASE")) {
+                if (value == null || value.equals("")) {
+                    throw new BadOption("Empty value of bind-file option " + option);
+                }
+                return true;
+            }
+
+            if (option.equals("DEBUGGEE_TESTED_JAVA_HOME")
+                    || option.equals("DEBUGGEE_WORKDIR")
+                    || option.equals("DEBUGGEE_TESTBASE")) {
+                if (value == null || value.equals("")) {
+                    throw new BadOption("Empty value of bind-file option " + option);
+                }
+                checkDir(option, value);
+                return true;
+            }
+
+            if (option.equals("DEBUGGEE_WINDIR")) {
+                if (!(value == null || value.equals(""))) {
+                    checkDir(option, value);
+                }
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
+         * Check if all recignized options form <i>bind-file</i> are compatible.
+         */
+        protected void checkAdditionalOptions() {
+
+            if (getDebuggerJavaHome() == null) {
+                throw new BadOption("Option DEBUGGER_JAVA_HOME missed from bind-file");
+            }
+            if (getDebuggerWorkDir() == null) {
+                throw new BadOption("Option DEBUGGER_WORKDIR missed from bind-file");
+            }
+            if (getDebuggerTestbase() == null) {
+                throw new BadOption("Option DEBUGGER_TESTBASE missed from bind-file");
+            }
+
+            if (getDebugeeJavaHome() == null) {
+                throw new BadOption("Option DEBUGGEE_JAVA_HOME missed from bind-file");
+            }
+            if (getDebugeeWorkDir() == null) {
+                throw new BadOption("Option DEBUGGEE_WORKDIR missed from bind-file");
+            }
+            if (getDebugeeTestbase() == null) {
+                throw new BadOption("Option DEBUGGEE_TESTBASE missed from bind-file");
+            }
+        }
+
+        /**
+         * Parse options form specified <i>bind-file</i>.
+         */
+        protected void parseAdditionalOptions() {
+            Enumeration keys = fileOptions.keys();
+            while (keys.hasMoreElements()) {
+                String option = (String)keys.nextElement();
+                String value = fileOptions.getProperty(option);
+                if (! checkAdditionalOption(option, value)) {
+                    throw new BadOption("Unrecognized bind-file option: " + option);
+                }
+            }
+            checkAdditionalOptions();
+        }
+
+        /**
+         * Parse all options from command line and specified <i>bind-file</i>.
+         */
+        protected void parseArguments() {
+            super.parseArguments();
+            String fileName = getBindFileName();
+            try {
+                FileInputStream bindFile = new FileInputStream(fileName);
+                fileOptions = new Properties();
+                fileOptions.load(bindFile);
+                bindFile.close();
+            } catch(FileNotFoundException e) {
+                throw new BadOption("Unable to open bind-file " + fileName + ": " + e);
+            } catch(IOException e) {
+                e.printStackTrace(log.getOutStream());
+                throw new Failure("Caught exception while reading bind-file:\n" + e);
+            }
+            parseAdditionalOptions();
+        }
+
+        /** Return name of specified <i>bind-file<i>. */
+        public String getBindFileName() {
+            return options.getProperty("bind.file");
+        }
+
+        /** Return specified debuggee host name . */
+        public String getDebuggerHost() {
+            return fileOptions.getProperty("DEBUGGER_HOST", "localhost");
+        }
+
+        /** Return string representation of port number for <code>BindServer<code> connection. */
+        public String getBindPort() {
+            return fileOptions.getProperty("BINDSERVER_PORT", "9000");
+        }
+
+        /** Return specified port number for <code>BindServer<code> connection. */
+        public int getBindPortNumber() {
+            try {
+                return Integer.parseInt(getBindPort());
+            } catch (NumberFormatException e) {
+                throw new Failure("Not integer value of BindServer port");
+            }
+        }
+
+        /** Return specified path to tested JDK used for debuggee VM. */
+        public String getDebugeeJavaHome() {
+            return fileOptions.getProperty("DEBUGGEE_TESTED_JAVA_HOME");
+        }
+
+        /** Return specified path to tested JDK used for debugger. */
+        public String getDebuggerJavaHome() {
+            return fileOptions.getProperty("DEBUGGER_TESTED_JAVA_HOME");
+        }
+
+        /** Return specified path to working dir from debuggee host. */
+        public String getDebugeeWorkDir() {
+            return fileOptions.getProperty("DEBUGGEE_WORKDIR");
+        }
+
+        /** Return specified path to working dir from debugger host. */
+        public String getDebuggerWorkDir() {
+            return fileOptions.getProperty("DEBUGGER_WORKDIR");
+        }
+
+        /** Return specified path to testbase dir from debuggee host. */
+        public String getDebugeeTestbase() {
+            return fileOptions.getProperty("DEBUGGEE_TESTBASE");
+        }
+
+        /** Return specified path to testbase dir from debugger host. */
+        public String getDebuggerTestbase() {
+            return fileOptions.getProperty("DEBUGGER_TESTBASE");
+        }
+
+        /** Return specified path to system directory on Wimdows platform. */
+        public String getDebugeeWinDir() {
+            return fileOptions.getProperty("DEBUGGEE_WINDIR");
+        }
+
+    } // ArgumentHandler
+
+} // BindServer
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ConversionUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jpda;
+
+/*
+Static methods checking whether given primitive type value can be
+converted to another primitive type without information loss
+
+Note:
+the spec defines following 2 types of primitive values conversions:
+
+Widening primitive conversions (don't loose information, but may lose precision):
+    * byte to short, int, long, float, or double
+    * short to int, long, float, or double
+    * char to int, long, float, or double
+    * int to long, float, or double
+    * long to float or double
+    * float to double
+
+Narrowing primitive conversions (may loose information and may loose precision):
+    * byte to char
+    * short to byte or char
+    * char to byte or short
+    * int to byte, short, or char
+    * long to byte, short, char, or int
+    * float to byte, short, char, int, or long
+    * double to byte, short, char, int, long, or float
+
+Examples:
+    Conversions (int)1234567890 -> (float)1.23456794E9 and (float)1.5 -> (int)1 loose precision.
+    Conversion  (byte)-1 -> (char) ffff and (double)Double.MAX_VALUE -> (int)Integer.MAX_VALUE loose information.
+
+(See the "JavaTM Language Specification" section 5.2 for more information
+on assignment compatibility)
+ */
+public class ConversionUtils {
+
+    /*
+     * Methods checking that value can be converted to the value of the
+     * same type (like 'informationLossByteToByte') were added to simplify
+     * clients coding (when this methods exist clients shouldn't handle this case
+     * in a specific way)
+     */
+
+    /*
+     * Byte
+     */
+    public static boolean informationLossByteToByte(Byte value) {
+        return false;
+    }
+
+    public static boolean informationLossByteToShort(Byte value) {
+        return false;
+    }
+
+    public static boolean informationLossByteToChar(Byte value) {
+        return (value.byteValue() > Character.MAX_VALUE) || (value.byteValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossByteToInt(Byte value) {
+        return false;
+    }
+
+    public static boolean informationLossByteToLong(Byte value) {
+        return false;
+    }
+
+    public static boolean informationLossByteToFloat(Byte value) {
+        return false;
+    }
+
+    public static boolean informationLossByteToDouble(Byte value) {
+        return false;
+    }
+
+    /*
+     * Short
+     */
+    public static boolean informationLossShortToShort(Short value) {
+        return false;
+    }
+
+    public static boolean informationLossShortToByte(Short value) {
+        return (value.shortValue() > Byte.MAX_VALUE) || (value.shortValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossShortToChar(Short value) {
+        return (value.shortValue() > Character.MAX_VALUE) || (value.shortValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossShortToInt(Short value) {
+        return false;
+    }
+
+    public static boolean informationLossShortToLong(Short value) {
+        return false;
+    }
+
+    public static boolean informationLossShortToFloat(Short value) {
+        return false;
+    }
+
+    public static boolean informationLossShortToDouble(Short value) {
+        return false;
+    }
+
+    /*
+     * Char
+     */
+    public static boolean informationLossCharToChar(Character value) {
+        return false;
+    }
+
+    public static boolean informationLossCharToByte(Character value) {
+        return (value.charValue() > Byte.MAX_VALUE) || (value.charValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossCharToShort(Character value) {
+        return (value.charValue() > Short.MAX_VALUE) || (value.charValue() < Short.MIN_VALUE);
+    }
+
+    public static boolean informationLossCharToInt(Character value) {
+        return false;
+    }
+
+    public static boolean informationLossCharToLong(Character value) {
+        return false;
+    }
+
+    public static boolean informationLossCharToFloat(Character value) {
+        return false;
+    }
+
+    public static boolean informationLossCharToDouble(Character value) {
+        return false;
+    }
+
+    /*
+     * Integer
+     */
+    public static boolean informationLossIntToInt(Integer value) {
+        return false;
+    }
+
+    public static boolean informationLossIntToByte(Integer value) {
+        return (value.intValue() > Byte.MAX_VALUE) || (value.intValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossIntToShort(Integer value) {
+        return (value.intValue() > Short.MAX_VALUE) || (value.intValue() < Short.MIN_VALUE);
+    }
+
+    public static boolean informationLossIntToChar(Integer value) {
+        return (value.intValue() > Character.MAX_VALUE) || (value.intValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossIntToLong(Integer value) {
+        return false;
+    }
+
+    public static boolean informationLossIntToFloat(Integer value) {
+        return false;
+    }
+
+    public static boolean informationLossIntToDouble(Integer value) {
+        return false;
+    }
+
+    /*
+     * Long
+     */
+    public static boolean informationLossLongToLong(Long value) {
+        return false;
+    }
+
+    public static boolean informationLossLongToByte(Long value) {
+        return (value.longValue() > Byte.MAX_VALUE) || (value.longValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossLongToShort(Long value) {
+        return (value.longValue() > Short.MAX_VALUE) || (value.longValue() < Short.MIN_VALUE);
+    }
+
+    public static boolean informationLossLongToChar(Long value) {
+        return (value.longValue() > Character.MAX_VALUE) || (value.longValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossLongToInt(Long value) {
+        return (value.longValue() > Integer.MAX_VALUE) || (value.longValue() < Integer.MIN_VALUE);
+    }
+
+    public static boolean informationLossLongToFloat(Long value) {
+        return false;
+    }
+
+    public static boolean informationLossLongToDouble(Long value) {
+        return false;
+    }
+
+    /*
+     * Float
+     */
+    public static boolean informationLossFloatToFloat(Float value) {
+        return false;
+    }
+
+    public static boolean informationLossFloatToByte(Float value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.floatValue() > Byte.MAX_VALUE) || (value.floatValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossFloatToShort(Float value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.floatValue() > Short.MAX_VALUE) || (value.floatValue() < Short.MIN_VALUE);
+    }
+
+    public static boolean informationLossFloatToChar(Float value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.floatValue() > Character.MAX_VALUE) || (value.floatValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossFloatToInt(Float value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.floatValue() > Integer.MAX_VALUE) || (value.floatValue() < Integer.MIN_VALUE)
+                || ((int)value.floatValue() != value.floatValue());
+    }
+
+    public static boolean informationLossFloatToLong(Float value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.floatValue() > Long.MAX_VALUE) || (value.floatValue() < Long.MIN_VALUE)
+                || ((long)value.floatValue() != value.floatValue());
+    }
+
+    public static boolean informationLossFloatToDouble(Float value) {
+        return false;
+    }
+
+
+    /*
+     * Double
+     */
+    public static boolean informationLossDoubleToDouble(Double value) {
+        return false;
+    }
+
+    public static boolean informationLossDoubleToByte(Double value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.doubleValue() > Byte.MAX_VALUE) || (value.doubleValue() < Byte.MIN_VALUE);
+    }
+
+    public static boolean informationLossDoubleToShort(Double value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.doubleValue() > Short.MAX_VALUE) || (value.doubleValue() < Short.MIN_VALUE);
+    }
+
+    public static boolean informationLossDoubleToChar(Double value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.doubleValue() > Character.MAX_VALUE) || (value.doubleValue() < Character.MIN_VALUE);
+    }
+
+    public static boolean informationLossDoubleToInt(Double value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.doubleValue() > Integer.MAX_VALUE) || (value.doubleValue() < Integer.MIN_VALUE);
+    }
+
+    public static boolean informationLossDoubleToLong(Double value) {
+        if (value.isInfinite())
+            return true;
+
+        if (value.isNaN())
+            return true;
+
+        return (value.doubleValue() > Long.MAX_VALUE) || (value.doubleValue() < Long.MIN_VALUE)
+                || ((long)value.doubleValue() != value.doubleValue());
+    }
+
+    public static boolean informationLossDoubleToFloat(Double value) {
+        if (value.isInfinite())
+            return false;
+
+        if (value.isNaN())
+            return false;
+
+        float f = (float) value.doubleValue();
+
+        return f != value.doubleValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,828 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import nsk.share.*;
+
+import java.io.*;
+import java.net.ServerSocket;
+
+/**
+ * Parser for JPDA test's launching and connection arguments.
+ * <p>
+ * <Code>DebugeeArgumentHandler</code> handles specific JDI/JDWP/JDB tests
+ * command line arguments related to launching and connection parameters
+ * for debugee VM in addition to general arguments recognized by
+ * <code>ArgumentParser</code>.
+ * <p>
+ * Following is the list of specific options for
+ * <code>DebugeeAgrumentHandler</code>:
+ * <ul>
+ * <li> <code>-test.host=</code>&lt;<i>host</i>&gt; -
+ *   address of a host where test executes
+ * <li> <code>-debugee.host=</code>&lt;<i>host</i>&gt; -
+ *   address of a host where debugee VM executes
+ * <li> <code>-connector=[attaching|listening]</code> -
+ *   connector type to connect to debugee VM
+ * <li> <code>-transport=[socket|shmem]</code> -
+ *   transport type to connect to debugee VM
+ * <li> <code>-transport.port=</code>&lt;<i>port</i>&gt; -
+ *   port number for <code>socket</code> transport
+ * <li> <code>-transport.shname=</code>&lt;<i>name</i>&gt; -
+ *   shared memory name for <code>shmem</code> transport
+ * <li> <code>-transport.address=</code>&lt;<i>dynamic</i>&gt; -
+ *   use dynamically allocated unique transport address for JDWP connection
+ *   ignoring settings for <code>-transport.port</code> and <code>-transport.shname</code>
+ *   (this works only with <code>-connector=listening</code> and <code>-transport=socket</code>)
+ * <li> <code>-debugee.suspend=[yes|no|default]</code> -
+ *   should debugee start in suspend mode or not
+ * <li> <code>-debugee.launch=[local|remote|manual]</code> -
+ *   launch and bind to debugee VM locally, remotely (via BindSever) or manually
+ * <li> <code>-debugee.vmhome=</code>&lt;<i>path</i>&gt; -
+ *   path to JDK used for launching debugee VM
+ * <li> <code>-debugee.vmkind=</code>&lt;<i>name</i>&gt; -
+ *   name of debugee VM launcher executable
+ * <li> <code>-debugee.vmkeys=</code>&lt;<i>string</i>&gt; -
+ *   additional options for launching debugee VM
+ * <li> <code>-jvmdi.strict=[yes|no|default]</code> -
+ *   using JVMDI strict mode
+ * <li> <code>-pipe.port=</code>&lt;<i>port</i>&gt; -
+ *   port number for internal IOPipe connection
+ * <li> <code>-bind.port=</code>&lt;<i>port</i>&gt; -
+ *   port number for BindServer connection
+ * </ul>
+ * <p>
+ * See also list of basic options recognized by
+ * <code>ArgumentParser</code>.
+ * <p>
+ * See also comments to <code>ArgumentParser</code> for list of general
+ * recognized options and how to work with command line arguments and options.
+ *
+ * @see ArgumentParser
+ * @see nsk.share.jdi.ArgumentHandler
+ * @see nsk.share.jdwp.ArgumentHandler
+ */
+public class DebugeeArgumentHandler extends ArgumentParser {
+
+    public static final String DEFAULT_PIPE_PORT                                = "7123";
+    public static final String DEFAULT_TRANSPORT_PORT                   = "8123";
+    public static final String DEFAULT_BIND_PORT                                = "9123";
+
+
+    /**
+     * Keep a copy of raw command-line arguments and parse them;
+     * but throw an exception on parsing error.
+     *
+     * @param  args  Array of the raw command-line arguments.
+     *
+     * @throws  BadOption  If unknown option or illegal
+     *                     option value found
+     *
+     * @see #setRawArguments(String[])
+     */
+    public DebugeeArgumentHandler(String args[]) {
+        super(args);
+    }
+
+    /**
+     * Return name of the host where test executes, specified by
+     * <code>-test.host</code> command line option or
+     * "<i>localhost</i>" string by default.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String getTestHost() {
+        return options.getProperty("test.host", "localhost");
+    }
+
+    /**
+     * Return name of host where the debugee VM is executed, specified by
+     * <code>-debugee.host</code> command line option or value of
+     * getTestHost() by default.
+     *
+     * @see #getTestHost()
+     * @see #setRawArguments(String[])
+     */
+    public String getDebugeeHost() {
+        return options.getProperty("debugee.host", getTestHost());
+    }
+
+    private boolean transportPortInited = false;
+    /**
+     * Return string representation of port number for socket transport,
+     * specified by <code>-tranport.port</code> command line option or
+     * "<code>DEFAULT_TRANSPORT_PORT</code>" string by default.
+     *
+     * @see #getTransportPortIfNotDynamic()
+     * @see #getTransportPortNumber()
+     * @see #setTransportPortNumber(int)
+     * @see #setRawArguments(String[])
+     */
+    synchronized public String getTransportPort() {
+        String port = options.getProperty("transport.port");
+        if (port == null) {
+            if (!transportPortInited) {
+                port = findFreePort();
+                if (port == null) {
+                    port = DEFAULT_TRANSPORT_PORT;
+                }
+                options.setProperty("transport.port", port);
+                transportPortInited = true;
+            }
+        }
+        return port;
+    }
+
+    /**
+     * Return string representation of port number for socket transport,
+     * specified by <code>-tranport.port</code> command line option or
+     * "<code>DEFAULT_TRANSPORT_PORT</code>" string by default in case transport address is
+     * not dynamic.
+     * Otherwise null is returned.
+     *
+     * @see #getTransportPort()
+     * @see #getTransportPortNumber()
+     * @see #setTransportPortNumber(int)
+     * @see #setRawArguments(String[])
+     */
+    public String getTransportPortIfNotDynamic() {
+        return ( isTransportAddressDynamic() ?
+                    null : getTransportPort() );
+    }
+
+    /**
+     * Return string port number for socket transport,
+     * specified by <code>-debugee.port</code> command line option or
+     * <code>DEFAULT_TRANSPORT_PORT</code> port number by default.
+     *
+     * @see #getTransportPort()
+     * @see #getTransportPortIfNotDynamic()
+     * @see #setTransportPortNumber(int)
+     * @see #setRawArguments(String[])
+     */
+    public int getTransportPortNumber() {
+        String value = getTransportPort();
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not integer value of \"-transport.port\" argument: " + value);
+        }
+    }
+
+    /**
+     * Add or replace value of option <code>-transport.port</code> in options list
+     * with the specified port number.
+     *
+     * @see #getTransportPortNumber()
+     * @see #setRawArguments(String[])
+     */
+    public void setTransportPortNumber(int port) {
+        String value = Integer.toString(port);
+        setOption("-", "transport.port", value);
+    }
+
+    /**
+     * Return shared name for shmem transport, specified by
+     * <code>-transport.shname</code> command line option, or
+     * "<i>nskjpdatestchannel</i>" + a process unique string by default.
+     *
+     * @see #setTransportSharedName(String)
+     * @see #setRawArguments(String[])
+     */
+    // Use a unique id for this process by default. This makes sure that
+    // tests running concurrently do not use the same shared name.
+    private static String defaultTransportSharedName
+            = "nskjpdatestchannel" + ProcessHandle.current().pid();
+    public String getTransportSharedName() {
+        return options.getProperty("transport.shname", defaultTransportSharedName);
+    }
+
+    /**
+     * Add or replace value of option <code>-transport.shname</code> in options list
+     * with the specified name.
+     *
+     * @see #getTransportSharedName()
+     * @see #setRawArguments(String[])
+     */
+    public void setTransportSharedName(String name) {
+        setOption("-", "transport.shname", name);
+    }
+
+    /**
+     * Return <i>true</i> if <code>-transport.address=dynamic</code> command line option
+     * is specified.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public boolean isTransportAddressDynamic() {
+        String value = options.getProperty("transport.address", null);
+        if (value != null && value.equals("dynamic"))
+            return true;
+        return false;
+    }
+
+    /**
+     * Return suspend mode for launching debugee VM, specified by
+     * <code>-debugee.suspend</code> command line option, or
+     * "<i>default</i>" string by default.
+     *
+     * @see #isDefaultDebugeeSuspendMode()
+     * @see #willDebugeeSuspended()
+     * @see #setRawArguments(String[])
+     */
+    public String getDebugeeSuspendMode() {
+        return options.getProperty("debugee.suspend", "default");
+    }
+
+    /**
+     * Return <i>true</i> if default suspend mode is used
+     * for launching debugee VM.
+     *
+     * @see #getDebugeeSuspendMode()
+     * @see #willDebugeeSuspended()
+     */
+    public boolean isDefaultDebugeeSuspendMode() {
+        String mode = getDebugeeSuspendMode();
+        return mode.equals("default");
+    }
+
+    /**
+     * Return <i>true</i> if debugee VM will be suspended after launching,
+     * either according to specified suspend mode or by default.
+     *
+     * @see #getDebugeeSuspendMode()
+     * @see #isDefaultDebugeeSuspendMode()
+     */
+    public boolean willDebugeeSuspended() {
+        if (isLaunchedLocally()) {
+            String mode = getDebugeeSuspendMode();
+            return mode.equals("no");
+        }
+        return true;
+    }
+
+    private boolean pipePortInited = false;
+    /**
+     * Return string representation of the port number for IOPipe connection,
+     * specified by <code>-pipe.port</code> command line option, or
+     * "<i>DEFAULT_PIPE_PORT</i>" string by default.
+     *
+     * @see #getPipePortNumber()
+     * @see #setPipePortNumber(int)
+     * @see #setRawArguments(String[])
+     */
+    synchronized public String getPipePort() {
+        String port = options.getProperty("pipe.port");
+        if (port == null) {
+            if (!pipePortInited) {
+                port = findFreePort();
+                if (port == null) {
+                    port = DEFAULT_PIPE_PORT;
+                }
+                pipePortInited = true;
+                options.setProperty("pipe.port", port);
+            }
+        }
+        return port;
+    }
+
+    /**
+     * Return port number for IOPipe connection,
+     * specified by <code>-pipe.port</code> command line option, or
+     * <i>DEFAULT_PIPE_PORT</i> port number by default.
+     *
+     * @see #getPipePort()
+     * @see #setPipePortNumber(int)
+     * @see #setRawArguments(String[])
+     */
+    public int getPipePortNumber() {
+        String value = getPipePort();
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not integer value of \"-pipe.port\" argument: " + value);
+        }
+    }
+
+    /**
+     * Add or replace value of option <code>-pipe.port</code> in options list
+     * with the specified port number.
+     *
+     * @see #getPipePortNumber()
+     * @see #setRawArguments(String[])
+     */
+    public void setPipePortNumber(int port) {
+        String value = Integer.toString(port);
+        setOption("-", "pipe.port", value);
+    }
+
+    /**
+     * Return debugee VM launching mode, specified by
+     * <code>-launch.mode</code> command line option, or
+     * "<i>local</i>" string by default.
+     *
+     * Possible values for this option are:
+     * <ul>
+     * <li> "<code>local</code>"
+     * <li> "<code>remote</code>"
+     * <li> "<code>manual</code>"
+     * </ul>
+     *
+     * @see #isLaunchedLocally()
+     * @see #isLaunchedRemotely()
+     * @see #isLaunchedManually()
+     * @see #setRawArguments(String[])
+     */
+    public String getLaunchMode() {
+        return options.getProperty("debugee.launch", "local");
+    }
+
+    /**
+     * Return <i>true</i> if debugee should be launched locally.
+     *
+     * @see #getLaunchMode()
+     */
+    public boolean isLaunchedLocally() {
+        return getLaunchMode().equals("local");
+    }
+
+    /**
+     * Return <i>true</i> if debugee should be launched remotely via
+     * BindServer.
+     *
+     * @see #getLaunchMode()
+     */
+    public boolean isLaunchedRemotely() {
+        return getLaunchMode().equals("remote");
+    }
+
+    /**
+     * Return <i>true</i> if debugee should be launched manually by user.
+     *
+     * @see #getLaunchMode()
+     */
+    public boolean isLaunchedManually() {
+        return getLaunchMode().equals("manual");
+    }
+
+    /**
+     * Return additional options for launching debugee VM, specified by
+     * <code>-launch.options</code> command line option, or
+     * empty string by default.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String getLaunchOptions() {
+        String result = options.getProperty("debugee.vmkeys", "").trim();
+        if (result.startsWith("\"") && result.endsWith("\"")) {
+            result = result.substring(1, result.length() - 1);
+        }
+        return result;
+    }
+
+    /**
+     * Return name of debugee VM launcher executable, specified by
+     * <code>-launch.vmexec</code> command line option, or
+     * "<i>java</i>" string by default.
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String getLaunchExecName() {
+        return options.getProperty("debugee.vmkind", "java");
+    }
+
+    /**
+     * Return full path to debugee VM launcher executable.
+     *
+     * @see #getLaunchExecName()
+     * @see #getLaunchExecPath(String)
+     * @see #getDebugeeJavaHome()
+     */
+    public String getLaunchExecPath() {
+        String java_home = getDebugeeJavaHome();
+        return getLaunchExecPath(java_home);
+    }
+
+    /**
+     * Return full path to VM launcher executable using givet JAVA_HOME path.
+     *
+     * @see #getLaunchExecName()
+     */
+    public String getLaunchExecPath(String java_home) {
+        String filesep = System.getProperty("file.separator");
+        return java_home + filesep + "bin" + filesep + getLaunchExecName();
+    }
+
+    /**
+     * Return full JAVA_HOME path for debugee VM.
+     *
+     * @see #getLaunchExecName()
+     */
+    public String getDebugeeJavaHome() {
+        String java_home = System.getProperty("java.home");
+        return options.getProperty("debugee.vmhome", java_home);
+    }
+
+    /**
+     * Return true if default debuggee VM launcher executable is used.
+     *
+     * @see #getLaunchExecName()
+     */
+    public boolean isDefaultLaunchExecName() {
+        String vmkind = options.getProperty("debugee.vmkind", null);
+        return (vmkind == null);
+    }
+
+    /**
+     * Return true if default JAVA_HOME path for debuggee VM is used.
+     *
+     * @see #getDebugeeJavaHome()
+     */
+    public boolean isDefaultDebugeeJavaHome() {
+        String java_home = options.getProperty("debugee.vmhome", null);
+        return (java_home == null);
+    }
+
+    private boolean bindPortInited = false;
+    /**
+     * Return string representation of the port number for BindServer connection,
+     * specified by <code>-bind.port</code> command line option, or
+     * "<i>DEFAULT_BIND_PORT</i>" string by default.
+     *
+     * @see #getBindPortNumber()
+     * @see #setRawArguments(String[])
+     */
+    public String getBindPort() {
+        String port = options.getProperty("bind.port");
+        if (port == null) {
+            if (!bindPortInited) {
+                port = findFreePort();
+                if (port == null) {
+                    port = DEFAULT_BIND_PORT;
+                }
+                options.setProperty("bind.port", port);
+                bindPortInited = true;
+            }
+        }
+        return port;
+    }
+
+    /**
+     * Return port number for BindServer connection,
+     * specified by <code>-bind.port</code> command line option, or
+     * "<i>DEFAULT_BIND_PORT</i>" port number by default.
+     *
+     * @see #getBindPort()
+     * @see #setRawArguments(String[])
+     */
+    public int getBindPortNumber() {
+        String value = getBindPort();
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            throw new TestBug("Not integer value of \"bind.port\" argument: " + value);
+        }
+    }
+
+    /**
+     * Return JVMDI strict mode for launching debugee VM, specified by.
+     * <code>-jvmdi.strict</code> command line option, or
+     * "<i>default</i>" string by default.
+     *
+     * Possible values for this option are:
+     * <ul>
+     * <li> "<code>yes</code>"
+     * <li> "<code>no</code>"
+     * <li> "<code>default</code>"
+     * </ul>
+     *
+     * @see #setRawArguments(String[])
+     */
+    public String getJVMDIStrictMode() {
+        return options.getProperty("jvmdi.strict", "default");
+    }
+
+    /**
+     * Return <i>true</i> if JVMDI strict mode for launching debugeeVM is used^
+     * either by specifying in command line or by default.
+     *
+     * @see #getJVMDIStrictMode()
+     * @see #isDefaultJVMDIStrictMode()
+     * @see #setRawArguments(String[])
+     */
+    public boolean isJVMDIStrictMode() {
+        String mode = getJVMDIStrictMode();
+        return mode.equals("yes");
+    }
+
+    /**
+     * Return <i>true</i> if JVMDI default strict mode for launching debugee VM is used.
+     *
+     * @see #getJVMDIStrictMode()
+     * @see #isJVMDIStrictMode()
+     * @see #setRawArguments(String[])
+     */
+    public boolean isDefaultJVMDIStrictMode() {
+        String mode = getJVMDIStrictMode();
+        return mode.equals("default");
+    }
+
+    /**
+     * Return type of JDI connector used for connecting to debugee VM, specified by
+     * <code>-connector</code> command line option, or
+     * "<i>listening</i>" string by default.
+     *
+     * Possible values for this option are:
+     * <ul>
+     * <li> "<code>attaching</code>"
+     * <li> "<code>listening</code>"
+     * </ul>
+     *
+     * @see #isAttachingConnector()
+     * @see #isListeningConnector()
+     * @see #setRawArguments(String[])
+     */
+    public String getConnectorType() {
+        return options.getProperty("connector", "listening");
+    }
+
+    /**
+     * Return <i>true</i> if type of the used JDI connector is <code>attaching</code>.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isAttachingConnector() {
+        return getConnectorType().equals("attaching");
+    }
+
+    /**
+     * Return <i>true</i> if type of the used JDI connector is <code>listening</code>.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isListeningConnector() {
+        return getConnectorType().equals("listening");
+    }
+
+    /**
+     * Return <i>true</i> if connector type is not actually specified.
+     * In this case getConnectorType() returns some default connector type.
+     *
+     * @see #getConnectorType()
+     */
+    public boolean isDefaultConnector() {
+        return options.getProperty("connector") == null;
+    }
+
+    /**
+     * Return type of JDWP transport for connecting to debugee VM, specified by
+     * <code>-transport</code> command line option, or
+     * "<i>socket</i>" string by default.
+     *
+     * Possible values for this option are:
+     * <ul>
+     * <li> "<code>socket</code>"
+     * <li> "<code>shmem</code>"
+     * </ul>
+     *
+     * @see #getTransportName()
+     * @see #isSocketTransport()
+     * @see #isShmemTransport()
+     * @see #setRawArguments(String[])
+     */
+    public String getTransportType() {
+        return options.getProperty("transport", "socket");
+    }
+
+    /**
+     * Return transport name corresponding to the used JDWP transport type.
+     *
+     * @see #getTransportType()
+     */
+    public String getTransportName() {
+        if (isSocketTransport()) {
+            return "dt_socket";
+        } else if (isShmemTransport()) {
+            return "dt_shmem";
+        } else {
+            throw new TestBug("Undefined transport type");
+        }
+    }
+
+    /**
+     * Return <i>true</i> if the used JDWP transport type is <code>socket</code>,
+     * either by specifying in command line or as a platform default transport.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isSocketTransport() {
+        String transport = getTransportType();
+        return transport.equals("socket");
+    }
+
+    /**
+     * Return <i>true</i> if the used JDWP transport type is <code>shmem</code>,
+     * either by specifying in command line or as a platform default transport.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isShmemTransport() {
+        String transport = getTransportType();
+        return transport.equals("shmem");
+    }
+
+    /**
+     * Return <i>true</i> if transport type is not actually specified.
+     * In this case getTransportType() returns some default transport kind.
+     *
+     * @see #getTransportType()
+     */
+    public boolean isDefaultTransport() {
+        return options.getProperty("transport") == null;
+    }
+
+    /**
+     * Create <code>Log</code> for debugee application using command line options.
+     */
+    public Log createDebugeeLog() {
+        return new Log(System.err, this);
+    };
+
+    /**
+     * Create IOPipe for debugee application using command line options.
+     */
+    public IOPipe createDebugeeIOPipe() {
+        return createDebugeeIOPipe(createDebugeeLog());
+    };
+
+    /**
+     * Create IOPipe for debugee application using connection
+     * parameters from the command line and specify Log.
+     */
+    public IOPipe createDebugeeIOPipe(Log log) {
+        return new IOPipe(this, log);
+    };
+
+    /**
+     * Check if an option is aloowed and has proper value.
+     * This method is invoked by <code>parseArgumentss()</code>
+     *
+     * @param option option name
+     * @param value string representation of value
+     *                      (could be an empty string too)
+     *              null if this option has no value
+     * @return <i>true</i> if option is allowed and has proper value
+     *         <i>false</i> if otion is not admissible
+     *
+     * @throws <i>BadOption</i> if option has an illegal value
+     *
+     * @see #parseArguments()
+     */
+    protected boolean checkOption(String option, String value) {
+
+        if(option.equals("traceAll"))
+            return true;
+
+        // option with any string value
+        if (option.equals("debugee.vmkeys")) {
+            return true;
+        }
+
+        // option with any nonempty string value
+        if (option.equals("test.host")
+            || option.equals("debugee.host")
+            || option.equals("debugee.vmkind")
+            || option.equals("debugee.vmhome")
+            || option.equals("transport.shname")) {
+            if (value.length() <= 0) {
+                throw new BadOption(option + ": cannot be an empty string");
+            }
+            return true;
+        }
+
+        // option with positive integer port value
+        if (option.equals("transport.port")
+            || option.equals("bind.port")
+            || option.equals("pipe.port")) {
+            try {
+                int number = Integer.parseInt(value);
+                if (number < 0) {
+                    throw new BadOption(option + ": must be a positive integer");
+                }
+            } catch (NumberFormatException e) {
+                throw new BadOption(option + ": must be an integer");
+            }
+            return true;
+        }
+
+        // options with enumerated values
+
+        if (option.equals("debugee.suspend")) {
+            if ((!value.equals("yes"))
+                && (!value.equals("no"))
+                && (!value.equals("default"))) {
+                throw new BadOption(option + ": must be one of: "
+                                           + "yes, no, default");
+            }
+            return true;
+        }
+
+        if (option.equals("debugee.launch")) {
+            if ((!value.equals("local"))
+                && (!value.equals("remote"))
+                && (!value.equals("manual"))) {
+                throw new BadOption(option + ": must be one of: "
+                                           + "local, remote, manual " + value);
+            }
+            return true;
+        }
+
+        if (option.equals("jvmdi.strict")) {
+            if ((!value.equals("yes"))
+                && (!value.equals("no"))
+                && (!value.equals("default"))) {
+                throw new BadOption(option + ": must be one of: "
+                                           + "yes, no, default");
+            }
+            return true;
+        }
+
+        if (option.equals("transport")) {
+            if ((!value.equals("socket"))
+                && (!value.equals("shmem"))) {
+                throw new BadOption(option + ": must be one of: "
+                                           + "socket, shmem");
+            }
+            return true;
+        }
+
+        if (option.equals("connector")) {
+            if ((!value.equals("attaching"))
+                && (!value.equals("listening"))) {
+                throw new BadOption(option + ": value must be one of: "
+                                           + "attaching, listening");
+            }
+            return true;
+        }
+
+        if (option.equals("transport.address")) {
+            if (!value.equals("dynamic")) {
+                throw new BadOption(option + ": must be only: "
+                                           + "dynamic");
+            }
+            return true;
+        }
+
+        return super.checkOption(option, value);
+    }
+
+    /**
+     * Check if the values of all options are consistent.
+     * This method is invoked by <code>parseArguments()</code>
+     *
+     * @throws <i>BadOption</i> if options have inconsistent values
+     *
+     * @see #parseArguments()
+     */
+    protected void checkOptions() {
+        super.checkOptions();
+    }
+
+    private String findFreePort() {
+        ServerSocket ss = null;
+        try {
+            ss = new ServerSocket(0);
+            return String.valueOf(ss.getLocalPort());
+        } catch (IOException e) {
+            return null;
+        } finally {
+            try {
+                ss.close();
+            } catch (Throwable t) {
+                // ignore
+            }
+        }
+    }
+
+} // DebugeeArgumentHandler
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import nsk.share.*;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * This class provides debugger with ability to launch
+ * debuggee VM and to make connection to it using JDI connector or
+ * JDWP transport.
+ * <p>
+ * The present version of <code>Binder</code> allows
+ * to launch debuggee VM either on local machine (<i>local</i> launch mode),
+ * or on remote host using <code>BindServer</code> utility
+ * (<i>remote</i> launch mode). Also there is an ability to launch
+ * debuggee VM manually as a separate process on local or remote machine
+ * (<i>manual</i> launch mode), which is usefull for debugging.
+ * All these launching modes are specified by command line option
+ * <code>-debugee.launch</code> recognized by <code>DebugeeArgumentHandler</code>.
+ * <p>
+ * <code>Binder</code> also makes it possible to establish TCP/IP
+ * connection between debugger and debuggee throw <code>IOPipe</code>
+ * object. This connection allows debugger to communicate with debuggee
+ * by exchanging with synchronization messages and data.
+ * <p>
+ * To launch debuggee VM and bind to it use <code>bindToDebugee()</code>
+ * method. This method construct mirror of debugee VM, represented by
+ * object of <code>DebugeeProcess</code> class or derived. This mirror object
+ * allows to control debuggee VM.
+ * <p>
+ * See also <code>nsk.share.jdi.Binder</code> and <code>nsk.share.jdwp.Binder</code>
+ * classes which provide launching and binding to debuggee VM using specific
+ * JDI and JDWP features.
+ *
+ * @see DebugeeArgumentHandler
+ * @see DebugeeProcess
+ * @see IOPipe
+ * @see BindServer
+ *
+ * @see nsk.share.jdi.Binder
+ * @see nsk.share.jdwp.Binder
+ */
+public class DebugeeBinder extends Log.Logger implements Finalizable {
+
+    private static final boolean IS_WINDOWS = System.getProperty("os.name")
+                                                    .toLowerCase()
+                                                    .startsWith("win");
+
+    public static int TRY_DELAY = 1000;                     // milliseconds
+
+    public static int CONNECT_TIMEOUT = 1 * 60 * 1000;      // milliseconds
+    public static int CONNECT_TRY_DELAY = 2 * 1000;         // milliseconds
+    public static int CONNECT_TRIES = CONNECT_TIMEOUT / CONNECT_TRY_DELAY;
+
+    public static int THREAD_TIMEOUT = 2 * CONNECT_TRY_DELAY;  // milliseconds
+    public static int PING_TIMEOUT = 30 * 1000;  // milliseconds
+
+    public static int SOCKET_TIMEOUT = 2 * 1000;  // milliseconds
+    public static int SOCKET_LINGER = 1;   // milliseconds
+
+    private static int TRACE_LEVEL_PACKETS = 10;
+    private static int TRACE_LEVEL_THREADS = 20;
+    private static int TRACE_LEVEL_ACTIONS = 30;
+    private static int TRACE_LEVEL_SOCKETS = 40;
+    private static int TRACE_LEVEL_IO = 50;
+
+    /**
+     * Default message prefix for <code>Binder</code> object.
+     */
+    public static final String LOG_PREFIX = "binder> ";
+
+    private DebugeeArgumentHandler argumentHandler = null;
+
+    /**
+     * Get version string.
+     */
+    public static String getVersion () {
+        return "@(#)Binder.java %I% %E%";
+    }
+
+    // -------------------------------------------------- //
+
+    private BindServerListener bindServerListener = null;
+    private ServerSocket pipeServerSocket = null;
+
+    // -------------------------------------------------- //
+
+    /**
+     * Incarnate new Binder obeying the given
+     * <code>argumentHandler</code>; and assign the given
+     * <code>log</code>.
+     */
+    public DebugeeBinder (DebugeeArgumentHandler argumentHandler, Log log) {
+        super(log, LOG_PREFIX);
+        this.argumentHandler = argumentHandler;
+        Finalizer finalizer = new Finalizer(this);
+        finalizer.activate();
+    }
+
+    /**
+     * Get argument handler of this binder object.
+     */
+    DebugeeArgumentHandler getArgumentHandler() {
+        return argumentHandler;
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Wait for given thread finished for THREAD_TIMEOUT timeout and
+     * interrupt this thread if not finished.
+     *
+     * @param thr thread to wait for
+     * @param logger to write log messages to
+     */
+    public static void waitForThread(Thread thr, Log.Logger logger) {
+        waitForThread(thr, THREAD_TIMEOUT, logger);
+    }
+
+    /**
+     * Wait for given thread finished for specified timeout and
+     * interrupt this thread if not finished.
+     *
+     * @param thr thread to wait for
+     * @param millisecs timeout in milliseconds
+     * @param logger to write log messages to
+     */
+    public static void waitForThread(Thread thr, long millisecs, Log.Logger logger) {
+        if (thr != null) {
+            if (thr.isAlive()) {
+                try {
+                    logger.trace(TRACE_LEVEL_THREADS, "Waiting for thread: " + thr.getName());
+                    thr.join(millisecs);
+                } catch (InterruptedException e) {
+                    e.printStackTrace(logger.getOutStream());
+                    throw new Failure ("Thread interrupted while waiting for another thread:\n\t"
+                                         + e);
+                } finally {
+                    if (thr.isAlive()) {
+                        logger.trace(TRACE_LEVEL_THREADS, "Interrupting not finished thread: " + thr);
+                        thr.interrupt();
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Make preperation for IOPipe connection before starting debugee VM process.
+     * May change options in the passed <code>argumentHandler</code>.
+     */
+    protected void prepareForPipeConnection(DebugeeArgumentHandler argumentHandler) {
+        if (argumentHandler.isTransportAddressDynamic()) {
+            try {
+                pipeServerSocket = new ServerSocket();
+                pipeServerSocket.setReuseAddress(false);
+                pipeServerSocket.bind(null);
+
+            } catch (IOException e) {
+                e.printStackTrace(getOutStream());
+                throw new Failure("Caught IOException while binding for IOPipe connection: \n\t"
+                                + e);
+            }
+
+            int port = pipeServerSocket.getLocalPort();
+            argumentHandler.setPipePortNumber(port);
+        }
+    }
+
+    /**
+     * Return already bound ServerSocket for IOPipe connection or null.
+     */
+    protected ServerSocket getPipeServerSocket() {
+        return pipeServerSocket;
+    }
+
+    /**
+     * Close ServerSocket used for IOPipeConnection if any.
+     */
+    private void closePipeServerSocket() {
+        if (pipeServerSocket != null) {
+            try {
+                pipeServerSocket.close();
+            } catch (IOException e) {
+                println("# WARNING: Caught IOException while closing ServerSocket used for IOPipe connection: \n\t"
+                        + e);
+            }
+        }
+    }
+
+    // -------------------------------------------------- //
+
+    /**
+     * Make environment for launching JVM process.
+     */
+    public String[] makeProcessEnvironment() {
+/*
+        String env = new String[0];
+        return env;
+ */
+        return null;
+    }
+
+    /**
+     * Launch process by the specified command line.
+     *
+     * @throws IOException if I/O error occured while launching process
+     */
+    public Process launchProcess(String cmdLine) throws IOException {
+        String env[] = makeProcessEnvironment();
+        return Runtime.getRuntime().exec(cmdLine, env);
+    }
+
+    /**
+     * Launch process by the arguments array.
+     *
+     * @throws IOException if I/O error occured while launching process
+     */
+    public Process launchProcess(String[] args) throws IOException {
+        String env[] = makeProcessEnvironment();
+        return Runtime.getRuntime().exec(args, env);
+    }
+
+    /**
+     * Make string representation of debuggee VM transport address according
+     * to current command line options.
+     */
+    public String makeTransportAddress() {
+        String address = null;
+        if (argumentHandler.isSocketTransport()) {
+            if (argumentHandler.isListeningConnector()) {
+                address = argumentHandler.getTestHost()
+                        + ":" + argumentHandler.getTransportPort();
+            } else {
+                address = argumentHandler.getTransportPort();
+            }
+        } else if (argumentHandler.isShmemTransport() ) {
+            address = argumentHandler.getTransportSharedName();
+        } else {
+            throw new TestBug("Undefined transport type: "
+                        + argumentHandler.getTransportType());
+        }
+        return address;
+    }
+
+    /**
+     * Make command line to launch debugee VM as a string using given quote symbol,
+     * using specified <code>transportAddress</code> for JDWP connection.
+     */
+    public String makeCommandLineString(String classToExecute, String transportAddress, String quote) {
+        String[] args = makeCommandLineArgs(classToExecute, transportAddress);
+        return ArgumentParser.joinArguments(args, quote);
+    }
+
+    /**
+     * Make command line to launch debugee VM as a string using given quote symbol.
+     */
+    public String makeCommandLineString(String classToExecute, String quote) {
+        return makeCommandLineString(classToExecute, makeTransportAddress(), quote);
+    }
+
+    /**
+     * Make command line to launch debugee VM as a string using default quote symbol,
+     * using specified <code>transportAddress</code> for JDWP connection.
+     */
+/*
+    public String makeCommandLineString(String classToExecute, String transportAddress) {
+        return makeCommandLineString(classToExecute, transportAddress, "\"");
+    }
+ */
+
+    /**
+     * Make command line to launch debugee VM as a string using default quote symbol.
+     */
+/*
+    public String makeCommandLineString(String classToExecute) {
+        return makeCommandLineString(classToExecute, makeTransportAddress());
+    }
+ */
+
+    /**
+     * Make command line to launch debugee VM as an array of arguments,
+     * using specified <code>transportAddress</code> for JDWP connection.
+     */
+    public String[] makeCommandLineArgs(String classToExecute, String transportAddress) {
+        Vector<String> args = new Vector<String>();
+
+        args.add(argumentHandler.getLaunchExecPath());
+
+        String javaOpts = argumentHandler.getLaunchOptions();
+        if (javaOpts != null && javaOpts.length() > 0) {
+            StringTokenizer st = new StringTokenizer(javaOpts);
+
+            while (st.hasMoreTokens()) {
+                args.add(st.nextToken());
+            }
+        }
+
+/*
+        String classPath = System.getProperty("java.class.path");
+        args.add("-classpath")
+        args.add(classPath);
+ */
+
+        args.add("-Xdebug");
+
+        String server;
+        if (argumentHandler.isAttachingConnector()) {
+            server = "y";
+        } else {
+            server = "n";
+        }
+
+        String jdwpArgs = "-Xrunjdwp:"
+                        + "server=" + server
+                        + ",transport=" + argumentHandler.getTransportName()
+                        + ",address=" + transportAddress;
+
+        if (! argumentHandler.isDefaultJVMDIStrictMode()) {
+            if (argumentHandler.isJVMDIStrictMode())
+                jdwpArgs += ",strict=y";
+            else
+                jdwpArgs += ",strict=n";
+        }
+
+        args.add(jdwpArgs);
+
+        if (classToExecute != null) {
+            StringTokenizer st = new StringTokenizer(classToExecute);
+
+            while (st.hasMoreTokens()) {
+                args.add(st.nextToken());
+            }
+        }
+
+        String[] rawArgs = argumentHandler.getRawArguments();
+        for (int i = 0; i < rawArgs.length; i++) {
+            String rawArg = rawArgs[i];
+            // " has to be escaped on windows
+            if (IS_WINDOWS) {
+                rawArg = rawArg.replace("\"", "\\\"");
+            }
+            args.add(rawArg);
+        }
+
+        String[] argsArray = new String[args.size()];
+        for (int i = 0; i < args.size(); i++) {
+            argsArray[i] = (String) args.elementAt(i);
+        }
+
+        return argsArray;
+    }
+
+    /**
+     * Make command line to launch debugee VM as an array of arguments.
+     */
+    public String[] makeCommandLineArgs(String classToExecute) {
+        return makeCommandLineArgs(classToExecute, makeTransportAddress());
+    }
+
+    /**
+     * Make connection to remote BindServer and start BindServerListener thread.
+     *
+     * @throws IOException if I/O error occured while connecting
+     */
+    public void connectToBindServer(String taskID) {
+        if (bindServerListener != null) {
+            throw new Failure("Connection to BindServer already exists");
+        }
+        try {
+            bindServerListener = new BindServerListener(this);
+            bindServerListener.setDaemon(true);
+            bindServerListener.connect(taskID);
+            bindServerListener.start();
+        } catch (IOException e) {
+            e.printStackTrace(getOutStream());
+            throw new Failure("Caught exception while connecting to BindServer:\n\t" + e);
+        }
+    }
+
+    /**
+     * Split string into list of substrings using specified separator.
+     */
+    private static String[] splitString(String givenString, String separator) {
+        Vector<String> tmpList = new Vector<String>();
+        StringTokenizer tokenizer = new StringTokenizer(givenString, separator);
+        while(tokenizer.hasMoreTokens()) {
+            tmpList.add(tokenizer.nextToken());
+        }
+        String[] list = new String[tmpList.size()];
+        for (int i = 0; i < tmpList.size(); i++) {
+            list[i] = tmpList.elementAt(i);
+        }
+        return list;
+    }
+
+    /**
+     * Send command to remote <code>BindServer</code> and receive reply.
+     *
+     * @throws IOException if I/O error occured while launching process
+     */
+    public synchronized Object sendRemoteCommand(Object command) {
+        try {
+            bindServerListener.sendCommand(command);
+            Object reply = bindServerListener.getReply();
+            return reply;
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Unexpected exception while sending command to BindServer:\n\t"
+                            + e);
+        }
+    }
+
+    /**
+     * Launch remote process using request to <code>BindServer</code>.
+     *
+     * @throws IOException if I/O error occured
+     */
+    public void launchRemoteProcess(String[] args) throws IOException {
+        String pathSeparator = System.getProperty("path.separator");
+        BindServer.LaunchDebugee command =
+            new BindServer.LaunchDebugee(args,
+                    System.getProperty("file.separator"),
+                    System.getProperty("user.dir"),
+                    splitString(System.getProperty("java.library.path"), pathSeparator),
+                    splitString(System.getProperty("java.class.path"), pathSeparator),
+                    splitString(System.getProperty("java.library.path"), pathSeparator));
+
+        Object reply = sendRemoteCommand(command);
+        if (reply instanceof BindServer.OK) {
+            // do nothing
+        } else if (reply instanceof BindServer.RequestFailed) {
+            BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
+            throw new Failure("BindServer error: " + castedReply.reason);
+        } else {
+            throw new Failure("Wrong reply from BindServer: " + reply);
+        }
+    }
+
+    /**
+     * Return exit status of the remotely launched process
+     * using request to <code>BindServer</code>.
+     */
+    public int getRemoteProcessStatus () {
+        Object reply = sendRemoteCommand(new BindServer.DebugeeExitCode());
+        if (reply instanceof BindServer.OK) {
+            BindServer.OK castedReply = (BindServer.OK)reply;
+            return (int)castedReply.info;
+        } else if (reply instanceof BindServer.CaughtException) {
+            BindServer.CaughtException castedReply = (BindServer.CaughtException)reply;
+            throw new IllegalThreadStateException(castedReply.reason);
+        } else if (reply instanceof BindServer.RequestFailed) {
+            BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
+            throw new Failure("BindServer error: " + castedReply.reason);
+        } else {
+            throw new Failure("Wrong reply from BindServer: " + reply);
+        }
+    }
+
+    /**
+     * Check whether the remotely launched process has been terminated
+     * using request to <code>BindServer</code>.
+     */
+    public boolean isRemoteProcessTerminated () {
+        try {
+            int value = getRemoteProcessStatus();
+            return true;
+        } catch (IllegalThreadStateException e) {
+            return false;
+        }
+    }
+
+    // ---------------------------------------------- //
+
+    /**
+     * Kill the remotely launched process
+     * using request to <code>BindServer</code>.
+     */
+    public void killRemoteProcess () {
+        Object reply = sendRemoteCommand(new BindServer.KillDebugee());
+        if (reply instanceof BindServer.OK) {
+            return;
+        } else if (reply instanceof BindServer.RequestFailed) {
+            BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
+            throw new Failure("BindServer error: " + castedReply.reason);
+        } else {
+            throw new Failure("Wrong reply from BindServer: " + reply);
+        }
+    }
+
+    /**
+     * Wait until the remotely launched process exits or crashes
+     * using request to <code>BindServer</code>.
+     */
+    public int waitForRemoteProcess () {
+
+        Object reply = sendRemoteCommand(new BindServer.WaitForDebugee(0));
+        if (reply instanceof BindServer.OK) {
+            BindServer.OK castedReply = (BindServer.OK)reply;
+            return (int)castedReply.info;
+        } else if (reply instanceof BindServer.RequestFailed) {
+            BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
+            throw new Failure("BindServer error: " + castedReply.reason);
+        } else {
+            throw new Failure("Wrong reply from BindServer: " + reply);
+        }
+    }
+
+    /**
+     * Close binder by closing all started threads.
+     */
+    public void close() {
+        if (bindServerListener != null) {
+            bindServerListener.close();
+        }
+        closePipeServerSocket();
+    }
+
+    /**
+     * Finalize binder by invoking <code>close()</code>.
+     *
+     * @throws Throwable if any throwable exception is thrown during finalization
+     */
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+
+    /**
+     * Finalize binder at exit by invoking <code>finalize()</code>.
+     *
+     * @throws Throwable if any throwable exception is thrown during finalization
+     */
+    public void finalizeAtExit() throws Throwable {
+        finalize();
+    }
+
+    /**
+     * Separate thread for listening connection from <code>BindServer</code>.
+     */
+    private class BindServerListener extends Thread {
+        private SocketConnection connection = null;
+        private Log.Logger logger = null;
+
+        /** List of received responses from <code>BindServer</code>. */
+        private LinkedList<BindServer.Response> replies = new LinkedList<BindServer.Response>();
+
+        /**
+         * Make thread.
+         */
+        public BindServerListener(Log.Logger logger) {
+            this.logger = logger;
+        }
+
+        /**
+         * Establish connection to <code>BindServer</code>.
+         */
+        public void connect(String taskID) throws IOException {
+            String host = argumentHandler.getDebugeeHost();
+            int port = argumentHandler.getBindPortNumber();
+            display("Connecting to BindServer: " + host + ":" + port);
+            connection = new SocketConnection(logger, "BindServer");
+//            connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT);
+            connection.attach(host, port);
+            handshake(taskID);
+        }
+
+        /**
+         * Receive OK(version) from BindServer and check received version number.
+         */
+        private void handshake(String taskID) {
+            // receive OK(version)
+            trace(TRACE_LEVEL_ACTIONS, "Waiting for initial OK(version) from BindServer");
+            Object reply = connection.readObject();
+            trace(TRACE_LEVEL_ACTIONS, "Got initial OK(version) from BindServer: " + reply);
+            if (reply instanceof BindServer.RequestFailed) {
+                BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
+                trace(TRACE_LEVEL_ACTIONS, "Reply is RequestFailed: throw Failure");
+                throw new Failure("BindServer error: " + castedReply.reason);
+            } else if (reply instanceof BindServer.OK) {
+                BindServer.OK castedReply = (BindServer.OK)reply;
+                trace(TRACE_LEVEL_ACTIONS, "Reply is OK: check BindServer version");
+                if (castedReply.info != BindServer.VERSION) {
+                    throw new Failure("Wrong version of BindServer: " + castedReply.info
+                                    + " (expected: " + BindServer.VERSION + ")");
+                }
+                display("Connected to BindServer: version " + castedReply.info);
+            } else {
+                trace(TRACE_LEVEL_ACTIONS, "Reply is unknown: throw Failure");
+                throw new Failure("Wrong reply from BindServer: " + reply);
+            }
+
+            // send TaskID(id)
+            try {
+                trace(TRACE_LEVEL_ACTIONS, "Sending TaskID(id) to BindServer");
+                sendCommand(new BindServer.TaskID(taskID));
+                trace(TRACE_LEVEL_ACTIONS, "Sent TaskID(id) to BindServer");
+            } catch (IOException e) {
+                throw new Failure("Caught IOException while sending TaskID(id) to BindServer:\n\t"
+                                + e);
+            }
+        }
+
+        /**
+         * Check if thread is connected to <code>BindServer</code>.
+         */
+        public boolean isConnected() {
+            return (connection != null && connection.isConnected());
+        }
+
+        /**
+         * Send a command to </code>BindServer</code>.
+         */
+        public synchronized void sendCommand(Object command) throws IOException {
+            connection.writeObject(command);
+        }
+
+        /**
+         * Receive response from <code>BindServer</code>.
+         */
+        public Object getReply() {
+            synchronized (replies) {
+                while (replies.isEmpty()) {
+                    if (!isConnected()) {
+                        throw new Failure("No reply from BindServer: connection lost");
+                    }
+                    try {
+                        replies.wait(TRY_DELAY);
+                    } catch (InterruptedException e) {
+                        e.printStackTrace(getOutStream());
+                        throw new Failure("Thread interrupted while waiting for reply from BindServer:\n\t"
+                                        + e);
+                    }
+                }
+                Object reply = replies.removeFirst();
+                if (reply == null) {
+                    throw new Failure("No reply from BindServer: connection lost");
+                }
+                return reply;
+            }
+        }
+
+        /**
+         * Add response object to the list of received responses.
+         */
+        private void addReply(BindServer.Response reply) {
+            synchronized (replies) {
+                replies.add(reply);
+                replies.notifyAll();
+            }
+        }
+
+        /**
+         * Read packets from <code>BindServer<code> connection and
+         * notify waiting thread if response or IOPipe message received.
+         * Received lines of redirected streams are put into log.
+         */
+        public void run() {
+            trace(TRACE_LEVEL_THREADS, "BindServerListener thread started");
+            try {
+                for (;;) {
+                    Object reply = connection.readObject();
+                    if (reply == null) {
+                        break;
+                    } else if (reply instanceof BindServer.Disconnect) {
+                        reply = null;
+                        trace(TRACE_LEVEL_ACTIONS, "Packet is Disconnect: close connection");
+                        break;
+                    } else if (reply instanceof BindServer.RedirectedStream) {
+                        BindServer.RedirectedStream castedReply = (BindServer.RedirectedStream)reply;
+                        trace(TRACE_LEVEL_ACTIONS, "Packet is RedirectedStream: put message into log");
+                        log.println(castedReply.line);
+                    } else if (reply instanceof BindServer.Response) {
+                        BindServer.Response castedReply = (BindServer.Response)reply;
+                        trace(TRACE_LEVEL_ACTIONS, "Packet is reply: notify all threads waiting for reply");
+                        addReply(castedReply);
+                    } else {
+                        trace(TRACE_LEVEL_ACTIONS, "Packet is unknown: throw Failure");
+                        throw new Failure("Wrong reply from BindServer: " + reply);
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace(getOutStream());
+                complain("Caught exception while reading packets from BindServer:\n\t" + e);
+            } finally {
+                closeConnection();
+                addReply(null);
+                trace(TRACE_LEVEL_THREADS, "BindServerListener thread finished");
+            }
+        }
+
+        /**
+         * Send Disconnect command to </code>BindServer</code>.
+         */
+        public void disconnect() {
+            if (connection == null) return;
+            try {
+                sendCommand(new BindServer.Disconnect());
+            } catch (IOException e) {
+                display("Caught IOException while requesting disconnection with BindServer");
+            }
+        }
+
+        /**
+         * Close socket connection.
+         */
+        public void closeConnection() {
+            if (connection != null) {
+                connection.close();
+            }
+        }
+
+        /**
+         * Wait for thread finished in the specified timeout or interrupt it.
+         */
+        public void waitForThread(long millis) {
+            DebugeeBinder.waitForThread(this, millis, logger);
+        }
+
+        /**
+         * Close this thread by waiting for it finishes or interrupt it
+         * and close socket connection.
+         */
+        public void close() {
+            disconnect();
+            waitForThread(DebugeeBinder.THREAD_TIMEOUT);
+            closeConnection();
+        }
+
+    } // BindServerListener
+
+} // DebugeeBinder
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import nsk.share.*;
+import java.io.*;
+import java.net.*;
+
+/**
+ * This class is used to control debugee VM process.
+ * <p>
+ * Object of this class is constructed by <code>DebugeeBinder</code>
+ * and is used as a mirror of debugee VM process.
+ * It provides abilities to launch such process,
+ * redirect standard output streams, wait for process terminates
+ * or kill the process, and so on.
+ * <p>
+ * This is an abstract class that declares abstract methods to control
+ * debugee VM process.
+ * Derived classes should implement these methods corresponding to the mode
+ * that the process should be started in (locally, remotely or manually).
+ * <p>
+ * Particular derived classes <code>nsk.share.jdi.Debugee</code> and
+ * <code>nsk.share.jdwp.Debugee</code> provides additional abilities
+ * to control debugee VM using JDI or JDWP specific features.
+ *
+ * @see DebugeeBinder
+ *
+ * @see nsk.share.jdi.Debugee
+ * @see nsk.share.jdwp.Debugee
+ */
+abstract public class DebugeeProcess extends FinalizableObject {
+
+    /** Default prefix for log messages. */
+    public static final String LOG_PREFIX = "binder> ";
+    public static final String DEBUGEE_STDOUT_LOG_PREFIX = "debugee.stdout> ";
+    public static final String DEBUGEE_STDERR_LOG_PREFIX = "debugee.stderr> ";
+
+    /** Messages prefix. */
+    protected String prefix = LOG_PREFIX;
+
+    /** Binder that creates this debugee process. */
+    protected DebugeeBinder binder = null;
+
+    /** Messages log from binder. */
+    protected Log log = null;
+
+    /** Communicational channel between debuger and debugee. */
+    protected IOPipe pipe = null;
+
+    /** Argument handler from binder. */
+    protected DebugeeArgumentHandler argumentHandler = null;
+
+    /** Need or not to check debuggee process termination at exit. */
+    protected boolean checkTermination = false;
+
+    /** Debugee VM process or <i>null</i> if not available. */
+    protected Process process = null;
+
+    /** Make new <code>Debugee</code> object for the given binder. */
+    protected DebugeeProcess (DebugeeBinder binder) {
+        this.binder = binder;
+        this.log = binder.getLog();
+    }
+
+    /**
+     * Return already bound ServerSocket for IOPipe connection or null.
+     */
+    protected ServerSocket getPipeServerSocket() {
+        return binder.getPipeServerSocket();
+    }
+
+    /** Return <code>DebugeeArgumentHandler</code> of the debugee object. */
+    public DebugeeArgumentHandler getArgumentHandler() {
+        return binder.getArgumentHandler();
+    }
+
+    /** Return <code>Log</code> of the debugee object. */
+    public Log getLog() {
+        return log;
+    }
+
+    /** Return <code>Process</code> object associated with debugee VM or <i>null</i>. */
+    public Process getProcess() {
+        return process;
+    }
+
+    // --------------------------------------------------- //
+
+    /** Created and return new IOPipe channel to the debugee VM. */
+    public IOPipe createIOPipe() {
+        if (pipe != null) {
+            throw new TestBug("IOPipe channel is already created");
+        }
+        pipe = new IOPipe(this);
+        return pipe;
+    }
+
+    /** Return IOPipe channel or null if not yet ctreated. */
+    public IOPipe getIOPipe() {
+        return pipe;
+    }
+
+    /** Receive and return signal from the debugee VM via IOPipe channel.
+     *
+     *  @throws TestBug if IOPipe channel is not created
+     */
+    public String receiveSignal() {
+        if ( pipe == null )
+            throw new TestBug("IOPipe channel is not initialized");
+        return pipe.readln();
+    }
+
+    /** Receive an expected <code>signal</code> from the debugee VM via IOPipe channel.
+     *
+     *  @throws Failure if received signal is not equal to the expected one
+     *  @throws TestBug if IOPipe channel is not created
+     */
+    public void receiveExpectedSignal(String signal) {
+        String line = receiveSignal();
+        if (line == null || !line.equals(signal))
+            throw new Failure("Received unexpected signal from debugee: " + line);
+        display("Received expected signal from debugee: " + signal);
+    }
+
+    /** Send <code>signal</code> to the debugee VM via IOPipe channel.
+     *
+     *  @throws TestBug if IOPipe channel is not defined created.
+     */
+    public void sendSignal(String signal) {
+        if (pipe == null)
+            throw new TestBug("IOPipe channel is not initialized");
+        pipe.println(signal);
+    }
+
+
+    // --------------------------------------------------- //
+
+    /** Wait until the debugee VM shutdown or crash. */
+    abstract protected int waitForDebugee () throws InterruptedException;
+
+    /** Kill the debugee VM. */
+    abstract protected void killDebugee ();
+
+    /** Check whether the debugee VM has been terminated. */
+    abstract public boolean terminated ();
+
+    /** Return the debugee VM exit status. */
+    abstract public int getStatus ();
+
+    /** Get a pipe to write to the debugee's stdin stream. */
+    abstract protected OutputStream getInPipe ();
+
+    /** Get a pipe to read the debugee's stdout stream. */
+    abstract protected InputStream getOutPipe ();
+
+    /** Get a pipe to read the debugee's stderr stream. */
+    abstract protected InputStream getErrPipe ();
+
+    // --------------------------------------------------- //
+
+    /**
+     * Wait until the debugee VM shutdown or crash,
+     * and let finish its stdout, stderr, and stdin
+     * redirectors (if any).
+     *
+     * @return  Debugee process exit code.
+     * @see #waitForRedirectors(long)
+     */
+    public int waitFor () {
+        long timeout = binder.getArgumentHandler().getWaitTime() * 60 * 1000;
+        int exitCode = 0;
+        try {
+            exitCode = waitForDebugee();
+        } catch (InterruptedException ie) {
+            ie.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while waiting for debuggee process: \n\t" + ie);
+        }
+        waitForRedirectors(timeout);
+        if (process != null) {
+            process.destroy();
+        }
+        return exitCode;
+    }
+
+    /**
+     * Wait until the debugee VM redirectors to complete for specified <code>timeout</code>.
+     *
+     * @see #waitFor()
+     */
+    public void waitForRedirectors (long timeout) {
+        try {
+            if (stdinRedirector != null) {
+                if (stdinRedirector.isAlive()) {
+                    stdinRedirector.join(timeout);
+                    if (stdinRedirector.isAlive()) {
+                        log.complain("Timeout for waiting STDIN redirector exceeded");
+                        stdinRedirector.interrupt();
+                    }
+                }
+                stdinRedirector = null;
+            };
+            if (stdoutRedirector != null) {
+                if (stdoutRedirector.isAlive()) {
+                    stdoutRedirector.join(timeout);
+                    if (stdoutRedirector.isAlive()) {
+                        log.complain("Timeout for waiting STDOUT redirector exceeded");
+                        stdoutRedirector.interrupt();
+                    }
+                }
+                stdoutRedirector = null;
+            };
+            if (stderrRedirector != null) {
+                if (stderrRedirector.isAlive()) {
+                    stderrRedirector.join(timeout);
+                    if (stderrRedirector.isAlive()) {
+                        log.complain("Timeout for waiting STDERR redirector exceeded");
+                        stderrRedirector.interrupt();
+                    }
+                }
+                stderrRedirector = null;
+            };
+        } catch (InterruptedException ie) {
+            ie.printStackTrace(log.getOutStream());
+            throw new Failure("Caught exception while waiting for debuggee output redirectors: \n\t"
+                                + ie);
+        }
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Get a pipe to write to the debugee's stdin stream,
+     * or throw TestBug exception is redirected.
+     */
+    final public OutputStream getStdin () {
+        if (stdinRedirector != null)
+            throw new TestBug("Debugee's stdin is redirected");
+        return getInPipe();
+    }
+
+    /**
+     * Get a pipe to read the debugee's stdout stream,
+     * or throw TestBug exception is redirected.
+     */
+    final public InputStream getStdout () {
+        if (stdoutRedirector != null)
+            throw new TestBug("Debugee's stdout is redirected");
+        return getOutPipe();
+    }
+
+    /**
+     * Get a pipe to read the debugee's stderr stream,
+     * or throw TestBug exception is redirected.
+     */
+    final public InputStream getStderr () {
+        if (stderrRedirector != null)
+            throw new TestBug("Debugee's stderr is redirected");
+        return getErrPipe();
+    }
+
+    // --------------------------------------------------- //
+
+    private IORedirector stdoutRedirector = null;
+    private IORedirector stderrRedirector = null;
+    private IORedirector stdinRedirector = null;
+
+//    /**
+//     * Start a thread redirecting the given <code>in</code> stream
+//     * to the debugee's stdin. If the debugee's stdin was already
+//     * redirected, the TestBug exception is thrown.
+//     */
+//    final public void redirectStdin(InputStream in) {
+//        if (stdinRedirector != null)
+//            throw new TestBug("the debugee's stdin is already redirected");
+//        stdinRedirector = new IORedirector(in,getInPipe());
+//        stdinRedirector.setName("IORedirector for stdin");
+//        stdinRedirector.setDaemon(true);
+//        stdinRedirector.start();
+//    }
+
+    /**
+     * Start thread redirecting the debugee's stdout to the
+     * given <code>out</code> stream. If the debugee's stdout
+     * was already redirected, the TestBug exception is thrown.
+     *
+     * @deprecated Use redirectStdout(Log, String) instead.
+     */
+    public void redirectStdout(OutputStream out) {
+        if (stdoutRedirector != null) {
+            return;
+        }
+//            throw new TestBug("Debugee's stdout is already redirected");
+        stdoutRedirector = new IORedirector(getOutPipe(),out);
+        stdoutRedirector.setPrefix(DEBUGEE_STDOUT_LOG_PREFIX);
+        stdoutRedirector.setName("IORedirector for stdout");
+        stdoutRedirector.setDaemon(true);
+        stdoutRedirector.start();
+    }
+
+    /**
+     * Start thread redirecting the debugee's stdout to the
+     * given <code>Log</code>. If the debugee's stdout
+     * was already redirected, the TestBug exception is thrown.
+     */
+    public void redirectStdout(Log log, String prefix) {
+        if (stdoutRedirector != null) {
+//            stdoutRedirector.setPrefix(prefix);
+            return;
+//            throw new TestBug("the debugee's stdout is already redirected");
+        }
+        stdoutRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getOutPipe())), log, prefix);
+        stdoutRedirector.setName("IORedirector for stdout");
+        stdoutRedirector.setDaemon(true);
+        stdoutRedirector.start();
+    }
+
+    /**
+     * Start thread redirecting the debugee's stderr to the
+     * given <code>err</code> stream. If the debugee's stderr
+     * was already redirected, the TestBug exception is thrown.
+     *
+     * @deprecated Use redirectStderr(Log, String) instead.
+     */
+    public void redirectStderr(OutputStream err) {
+        if (stderrRedirector != null) {
+            return;
+        }
+//            throw new TestBug("Debugee's stderr is already redirected");
+        stderrRedirector = new IORedirector(getErrPipe(),err);
+        stderrRedirector.setPrefix(DEBUGEE_STDERR_LOG_PREFIX);
+        stdoutRedirector.setName("IORedirector for stderr");
+        stderrRedirector.setDaemon(true);
+        stderrRedirector.start();
+    }
+
+    /**
+     * Start thread redirecting the debugee's stderr to the
+     * given <code>Log</code>. If the debugee's stderr
+     * was already redirected, the TestBug exception is thrown.
+     */
+    public void redirectStderr(Log log, String prefix) {
+        if (stderrRedirector != null) {
+//            stderrRedirector.setPrefix(prefix);
+            return;
+//            throw new TestBug("Debugee's stderr is already redirected");
+        }
+        stderrRedirector = new IORedirector(new BufferedReader(new InputStreamReader(getErrPipe())), log, prefix);
+        stdoutRedirector.setName("IORedirector for stderr");
+        stderrRedirector.setDaemon(true);
+        stderrRedirector.start();
+    }
+
+    /**
+     * Start thread redirecting the debugee's stdout/stderr to the
+     * given <code>Log</code> using standard prefixes.
+     * If the debugee's stdout/stderr were already redirected,
+     * the TestBug exception is thrown.
+     */
+    public void redirectOutput(Log log) {
+        redirectStdout(log, "debugee.stdout> ");
+        redirectStderr(log, "debugee.stderr> ");
+    }
+    // --------------------------------------------------- //
+
+    /**
+     * Kill the debugee VM if it is not terminated yet.
+     *
+     * @throws Throwable if any throwable exception is thrown during finalization
+     */
+    public void close() {
+        if (checkTermination) {
+            if (!terminated()) {
+                complain("Debugee VM has not exited correctly: trying to kill it");
+                killDebugee();
+            }
+            checkTermination = false;
+        }
+    }
+
+    // --------------------------------------------------- //
+
+    /**
+     * Display log message with prefix.
+     */
+    protected void display(String message) {
+        log.display(prefix + message);
+    }
+
+    /**
+     * Complain about error with specified message.
+     */
+    protected void complain(String message) {
+        log.complain(prefix + message);
+    }
+
+    /**
+     * Finalize debuggee VM wrapper by invoking <code>close()</code>.
+     *
+     * @throws Throwable if any throwable exception is thrown during finalization
+     */
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,1038 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//    THIS TEST IS LINE NUMBER SENSITIVE
+
+package nsk.share.jpda;
+
+import java.net.*;
+import nsk.share.*;
+
+// ForceEarlyReturnTestThread intended for testing ForceEarlyReturn functionality.
+//
+// ForceEarlyReturnTestThread contains test methods with different return type
+// (types corresponds to subclasses of com.sun.jdi.Value or JDWP type identifiers).
+// Debugger VM should set breakpoint on line log("...") and when test thread stop at breakpoint call
+// forceEarlyReturn(), so instructions after breakpoint shouldn't be executed(unexpectedMethod() shouldn't be called)
+// When started thread executes all test methods in order assigned in 'testedTypesNames' array.
+// It is possible to run this thread in 'testThread' mode, in this mode thread check that values returned from
+// test methods equals to those that should be returned through forceEarlyReturn, and no
+// instructions was executed in called method after force return (finally blocks are not executed too).
+// In non-testThread mode thread check that values returned from test methods was not changed.
+public class ForceEarlyReturnTestThread
+extends Thread
+{
+    void VoidMethod()
+    {
+        try
+        {
+            log("in void method"); // breakpointLines[0]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+    }
+
+    boolean BooleanMethod()
+    {
+        try
+        {
+            log("in boolean method"); // breakpointLines[1]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedBooleanValue;
+    }
+
+    byte ByteMethod()
+    {
+        try
+        {
+            log("in byte method"); // breakpointLines[2]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedByteValue;
+    }
+
+    short ShortMethod()
+    {
+        try
+        {
+            log("in short method"); // breakpointLines[3]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedShortValue;
+    }
+
+    char CharMethod()
+    {
+        try
+        {
+            log("in char method"); // breakpointLines[4]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedCharValue;
+    }
+
+    int IntMethod()
+    {
+        try
+        {
+            log("in int method"); // breakpointLines[5]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedIntValue;
+    }
+
+    long LongMethod()
+    {
+        try
+        {
+            log("in long method"); // breakpointLines[6]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedLongValue;
+    }
+
+    float FloatMethod()
+    {
+        try
+        {
+            log("in float method"); // breakpointLines[7]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedFloatValue;
+    }
+
+    double DoubleMethod()
+    {
+        try
+        {
+            log("in double method"); // breakpointLines[8]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedDoubleValue;
+    }
+
+    Object[] ObjectArrayMethod()
+    {
+        try
+        {
+            log("in object array method"); // breakpointLines[9]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedObjectArrayValue;
+    }
+
+    String StringMethod()
+    {
+        try
+        {
+            log("in string method"); // breakpointLines[10]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedStringValue;
+    }
+
+    Thread ThreadMethod()
+    {
+        try
+        {
+            log("in thread method"); // breakpointLines[11]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedThreadValue;
+    }
+
+    ThreadGroup ThreadGroupMethod()
+    {
+        try
+        {
+            log("in thread group method"); // breakpointLines[12]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedThreadGroupValue;
+    }
+
+    Class<?> ClassObjectMethod()
+    {
+        try
+        {
+            log("in class object method"); // breakpointLines[13]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedClassObjectValue;
+    }
+
+    ClassLoader ClassLoaderMethod()
+    {
+        try
+        {
+            log("in class loader method"); // breakpointLines[14]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedClassLoaderValue;
+    }
+
+    Object ObjectMethod()
+    {
+        try
+        {
+            log("in object method"); // breakpointLines[15]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedObjectValue;
+    }
+
+    Boolean BooleanWrapperMethod()
+    {
+        try
+        {
+            log("in boolean wrapper method"); // breakpointLines[16]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedBooleanWrapperValue;
+    }
+
+    Byte ByteWrapperMethod()
+    {
+        try
+        {
+            log("in byte wrapper method"); // breakpointLines[17]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedByteWrapperValue;
+    }
+
+    Short ShortWrapperMethod()
+    {
+        try
+        {
+            log("in short wrapper method"); // breakpointLines[18]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedShortWrapperValue;
+    }
+
+    Character CharWrapperMethod()
+    {
+        try
+        {
+            log("in char wrapper method"); // breakpointLines[19]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedCharWrapperValue;
+    }
+
+    Integer IntWrapperMethod()
+    {
+        try
+        {
+            log("in int wrapper method"); // breakpointLines[20]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedIntWrapperValue;
+    }
+
+    Long LongWrapperMethod()
+    {
+        try
+        {
+            log("in long wrapper method"); // breakpointLines[21]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedLongWrapperValue;
+    }
+
+    Float FloatWrapperMethod()
+    {
+        try
+        {
+            log("in float wrapper method"); // breakpointLines[22]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedFloatWrapperValue;
+    }
+
+    Double DoubleWrapperMethod()
+    {
+        try
+        {
+            log("in double wrapper method"); // breakpointLines[23]
+        }
+        finally
+        {
+            unexpectedMethod();
+        }
+
+        unexpectedMethod();
+
+        return unexpectedDoubleWrapperValue;
+    }
+
+    private void log(String message)
+    {
+        log.display(currentThread().getName() + ": " + message);
+    }
+
+    private void logError(String message)
+    {
+        log.complain(currentThread().getName() + ": " + message);
+    }
+
+    // values which should be passed in forceEarlyReturn():
+
+    public static boolean expectedBooleanValue = Boolean.TRUE;
+    public static byte expectedByteValue = Byte.MAX_VALUE;
+    public static char expectedCharValue = Character.MAX_VALUE;
+    public static short expectedShortValue = Short.MAX_VALUE;
+    public static int expectedIntValue = Integer.MAX_VALUE;
+    public static long expectedLongValue = Long.MAX_VALUE;
+    public static float expectedFloatValue = Float.MAX_VALUE;
+    public static double expectedDoubleValue = Double.MAX_VALUE;
+    public static Object[] expectedObjectArrayValue = new Object[1000];
+    public static Thread expectedThreadValue = new Thread();
+    public static ThreadGroup expectedThreadGroupValue = new ThreadGroup("Expected thread group");
+    public static Class<?> expectedClassObjectValue = ForceEarlyReturnTestThread.class;
+    public static ClassLoader expectedClassLoaderValue = new URLClassLoader(new URL[]{});
+    public static String expectedStringValue = "EXPECTED STRING";
+    public static Object expectedObjectValue = new Object();
+    public static Boolean expectedBooleanWrapperValue = new Boolean(Boolean.TRUE);
+    public static Byte expectedByteWrapperValue = new Byte(Byte.MAX_VALUE);
+    public static Character expectedCharWrapperValue = new Character(Character.MAX_VALUE);
+    public static Short expectedShortWrapperValue = new Short(Short.MAX_VALUE);
+    public static Integer expectedIntWrapperValue = new Integer(Integer.MAX_VALUE);
+    public static Long expectedLongWrapperValue = new Long(Long.MAX_VALUE);
+    public static Float expectedFloatWrapperValue = new Float(Float.MAX_VALUE);
+    public static Double expectedDoubleWrapperValue = new Double(Double.MAX_VALUE);
+
+    // values which should be returned from test methods without forceEarlyReturn():
+
+    public static boolean unexpectedBooleanValue = Boolean.FALSE;
+    public static byte unexpectedByteValue = 0;
+    public static char unexpectedCharValue = 0;
+    public static short unexpectedShortValue = 0;
+    public static int unexpectedIntValue = 0;
+    public static long unexpectedLongValue = 0;
+    public static float unexpectedFloatValue = 0;
+    public static double unexpectedDoubleValue = 0;
+    public static Object[] unexpectedObjectArrayValue = new Object[1000];
+    public static String unexpectedStringValue = "UNEXPECTED STRING";
+    public static Thread unexpectedThreadValue = new Thread();
+    public static ThreadGroup unexpectedThreadGroupValue = new ThreadGroup("Unexpected thread group");
+    public static Class<?> unexpectedClassObjectValue = Object.class;
+    public static ClassLoader unexpectedClassLoaderValue = new URLClassLoader(new URL[]{});
+    public static Object unexpectedObjectValue = new Object();
+    public static Boolean unexpectedBooleanWrapperValue = new Boolean(Boolean.FALSE);
+    public static Byte unexpectedByteWrapperValue = new Byte((byte)0);
+    public static Character unexpectedCharWrapperValue = new Character((char)0);
+    public static Short unexpectedShortWrapperValue = new Short((short)0);
+    public static Integer unexpectedIntWrapperValue = new Integer(0);
+    public static Long unexpectedLongWrapperValue = new Long(0);
+    public static Float unexpectedFloatWrapperValue = new Float(0);
+    public static Double unexpectedDoubleWrapperValue = new Double(0);
+
+    public static int[] breakpointLines = {
+        49,
+        63,
+        79,
+        95,
+        111,
+        127,
+        143,
+        159,
+        175,
+        191,
+        207,
+        223,
+        239,
+        255,
+        271,
+        287,
+        303,
+        319,
+        335,
+        351,
+        367,
+        383,
+        399,
+        415};
+
+    /* Invalid data for ForceEarlyReturn, needed to check is ForceEarlyReturn complies with following part of specification:
+     * Object values must be assignment compatible with the method return type
+     * (This implies that the method return type must be loaded through the enclosing class's class loader).
+     * Primitive values must be either assignment compatible with the method return type or must
+     * be convertible to the variable type without loss of information.
+     */
+    public static boolean invalidVoidValue = Boolean.TRUE;
+    public static boolean invalidObjectValue = Boolean.TRUE;
+    public static byte invalidBooleanValue = Byte.MAX_VALUE;
+    public static short invalidByteValue = Short.MAX_VALUE;
+    public static char invalidShortValue = Character.MAX_VALUE;
+    public static int invalidCharValue = Integer.MAX_VALUE;
+    public static long invalidIntValue = Long.MAX_VALUE;
+    public static float invalidLongValue = Float.MAX_VALUE;
+    public static double invalidFloatValue = Double.MAX_VALUE;
+    public static Object[] invalidDoubleValue = new Object[1000];
+    public static String invalidObjectArrayValue = "EXPECTED STRING";
+    public static Thread invalidStringValue = new Thread("Invalid thread");
+    public static ThreadGroup invalidThreadValue = new ThreadGroup("Invalid thread group");
+    public static Class<?> invalidThreadGroupValue = ForceEarlyReturnTestThread.class;
+    public static ClassLoader invalidClassObjectValue = new URLClassLoader(new URL[]{});
+    public static Object invalidClassLoaderValue = new Object();
+    public static Byte invalidBooleanWrapperValue = new Byte(Byte.MAX_VALUE);
+    public static Short invalidByteWrapperValue = new Short(Short.MAX_VALUE);
+    public static Character invalidShortWrapperValue = new Character(Character.MAX_VALUE);
+    public static Integer invalidCharWrapperValue = new Integer(Integer.MAX_VALUE);
+    public static Long invalidIntWrapperValue = new Long(Long.MAX_VALUE);
+    public static Float invalidLongWrapperValue = new Float(Float.MAX_VALUE);
+    public static Double invalidFloatWrapperValue = new Double(Double.MAX_VALUE);
+    public static Object[] invalidDoubleWrapperValue = new Object[1000];
+
+    // names of tested types, this names can be used to derive names of tested methods(typeName + 'Method'),
+    // names of fields containing predefined data to be returned through ForceEarlyReturn('expected' + typeName + 'Value'),
+    // names of fields containing invalid data for ForceEarlyReturn(needed to check is ForceEarlyReturn complies with its specification('invalid' + typeName + 'Value'))
+    public static String testedTypesNames[] =
+    {
+        "Void",
+        "Boolean",
+        "Byte",
+        "Short",
+        "Char",
+        "Int",
+        "Long",
+        "Float",
+        "Double",
+        "ObjectArray",
+        "String",
+        "Thread",
+        "ThreadGroup",
+        "ClassObject",
+        "ClassLoader",
+        "Object",
+        "BooleanWrapper",
+        "ByteWrapper",
+        "ShortWrapper",
+        "CharWrapper",
+        "IntWrapper",
+        "LongWrapper",
+        "FloatWrapper",
+        "DoubleWrapper",
+        };
+
+    private Log log;
+
+    // is forceEarlyReturn would called for this thread
+    private boolean isTestThread;
+
+    // how many times call all test methods (zero means infinite execution)
+    private int iterationsNumber = 1;
+
+    // test thread wait on 'startExecutionWicket' in beginning of run()
+    private Wicket startExecutionWicket = new Wicket();
+
+    private boolean success = true;
+
+    public ForceEarlyReturnTestThread(Log log, boolean isTestThread, int iterationNumber)
+    {
+        this.log = log;
+        this.isTestThread = isTestThread;
+
+        this.iterationsNumber = iterationNumber;
+    }
+
+    private volatile boolean stopExecution;
+
+    public void stopExecution()
+    {
+        stopExecution = true;
+    }
+
+    public void startExecuion()
+    {
+        startExecutionWicket.unlockAll();
+    }
+
+    public void run()
+    {
+        // first, debuggee VM starts and suspends test threads to let debugger initialize breakpoints
+        startExecutionWicket.waitFor();
+
+        int iterationCount = 0;
+
+        // test thread executes test methods 'iterationNumber' times
+        // non-test thread execute until not interrupted
+        // (iterationsNumber = 0 means infinite execution)
+        while(!stopExecution && (!isTestThread || ((iterationsNumber == 0) || (iterationCount++ < iterationsNumber))))
+        {
+            // execute test methods in order given in 'testMethodsNames' array
+            for(int i = 0; (i < testedTypesNames.length) && !stopExecution; i++)
+            {
+                executeMethod(testedTypesNames[i] + "Method");
+
+                /*
+                 * Small delay was inserted because of if test starts several ForceEarlyReturnTestThreads
+                 * with parameter isTestThread = false, these threads may consume too many CPU time and test
+                 * execution will be very slow
+                 */
+                if (!isTestThread) {
+                    try {
+                        Thread.sleep(1);
+                    } catch (InterruptedException e) {
+                        logError("Unexpected exception: " + e);
+                        e.printStackTrace(log.getOutStream());
+                        success = false;
+                    }
+                }
+            }
+        }
+
+        log("Test thread exit");
+    }
+
+    // execute test method and check that correct value is returned
+    private void executeMethod(String methodName)
+    {
+        if(methodName.equals("VoidMethod"))
+        {
+            VoidMethod();
+        }
+        if(methodName.equals("BooleanMethod"))
+        {
+            boolean result = BooleanMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            boolean expectedResult;
+
+            expectedResult = isTestThread ? expectedBooleanValue : unexpectedBooleanValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ByteMethod"))
+        {
+            byte result = ByteMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            byte expectedResult;
+
+            expectedResult = isTestThread ? expectedByteValue : unexpectedByteValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("CharMethod"))
+        {
+            char result = CharMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            char expectedResult;
+
+            expectedResult = isTestThread ? expectedCharValue : unexpectedCharValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ShortMethod"))
+        {
+            short result = ShortMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            short expectedResult;
+
+            expectedResult = isTestThread ? expectedShortValue : unexpectedShortValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("IntMethod"))
+        {
+            int result = IntMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            int expectedResult;
+
+            expectedResult = isTestThread ? expectedIntValue : unexpectedIntValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("LongMethod"))
+        {
+            long result = LongMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            long expectedResult;
+
+            expectedResult = isTestThread ? expectedLongValue : unexpectedLongValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("FloatMethod"))
+        {
+            float result = FloatMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            float expectedResult;
+
+            expectedResult = isTestThread ? expectedFloatValue : unexpectedFloatValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("DoubleMethod"))
+        {
+            double result = DoubleMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            double expectedResult;
+
+            expectedResult = isTestThread ? expectedDoubleValue : unexpectedDoubleValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("StringMethod"))
+        {
+            String result = StringMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            String expectedResult;
+
+            expectedResult = isTestThread ? expectedStringValue : unexpectedStringValue;
+
+            if(!result.equals(expectedResult))
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ObjectMethod"))
+        {
+            Object result = ObjectMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Object expectedResult;
+
+            expectedResult = isTestThread ? expectedObjectValue : unexpectedObjectValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ObjectArrayMethod"))
+        {
+            Object[] result = ObjectArrayMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Object[] expectedResult;
+
+            expectedResult = isTestThread ? expectedObjectArrayValue : unexpectedObjectArrayValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ThreadMethod"))
+        {
+            Thread result = ThreadMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Thread expectedResult;
+
+            expectedResult = isTestThread ? expectedThreadValue : unexpectedThreadValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ThreadGroupMethod"))
+        {
+            ThreadGroup result = ThreadGroupMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            ThreadGroup expectedResult;
+
+            expectedResult = isTestThread ? expectedThreadGroupValue : unexpectedThreadGroupValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ClassObjectMethod"))
+        {
+            Class<?> result = ClassObjectMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Class<?> expectedResult;
+
+            expectedResult = isTestThread ? expectedClassObjectValue : unexpectedClassObjectValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ClassLoaderMethod"))
+        {
+            ClassLoader result = ClassLoaderMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            ClassLoader expectedResult;
+
+            expectedResult = isTestThread ? expectedClassLoaderValue : unexpectedClassLoaderValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("BooleanWrapperMethod"))
+        {
+            Boolean result = BooleanWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Boolean expectedResult;
+
+            expectedResult = isTestThread ? expectedBooleanWrapperValue : unexpectedBooleanWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ByteWrapperMethod"))
+        {
+            Byte result = ByteWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Byte expectedResult;
+
+            expectedResult = isTestThread ? expectedByteWrapperValue : unexpectedByteWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("ShortWrapperMethod"))
+        {
+            Short result = ShortWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Short expectedResult;
+
+            expectedResult = isTestThread ? expectedShortWrapperValue : unexpectedShortWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("CharWrapperMethod"))
+        {
+            Character result = CharWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Character expectedResult;
+
+            expectedResult = isTestThread ? expectedCharWrapperValue : unexpectedCharWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("IntWrapperMethod"))
+        {
+            Integer result = IntWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Integer expectedResult;
+
+            expectedResult = isTestThread ? expectedIntWrapperValue : unexpectedIntWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("LongWrapperMethod"))
+        {
+            Long result = LongWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Long expectedResult;
+
+            expectedResult = isTestThread ? expectedLongWrapperValue : unexpectedLongWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("FloatWrapperMethod"))
+        {
+            Float result = FloatWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Float expectedResult;
+
+            expectedResult = isTestThread ? expectedFloatWrapperValue : unexpectedFloatWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+        if(methodName.equals("DoubleWrapperMethod"))
+        {
+            Double result = DoubleWrapperMethod();
+
+            // log(Thread.currentThread() + ": result of " + methodName + ": " + result);
+
+            Double expectedResult;
+
+            expectedResult = isTestThread ? expectedDoubleWrapperValue : unexpectedDoubleWrapperValue;
+
+            if(result != expectedResult)
+            {
+                logError("unexpected result of "  + methodName + ": " + result + ", expected is: " + expectedResult);
+                success = false;
+            }
+        }
+    }
+
+    // method which shouldn't be executed in test thread
+    void unexpectedMethod()
+    {
+        if(isTestThread)
+        {
+            success = false;
+            logError("unexpected code is executed after forceEarlyReturn");
+        }
+    }
+
+    public boolean getSuccess()
+    {
+        return success;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import nsk.share.*;
+
+/**
+ * This class implements communicational channel between
+ * debugger and debugee used for synchronization and data exchange.
+ * This channel is based on TCP/IP sockets and works in all
+ * modes (local, remote and manual). In a remote mode
+ * connection to <code>BindServer</code> is used for redirecting IOPipe messages.
+ * In all other modes direct TCP/IP coonnection between two VMs is used.
+ *
+ * @see BindServer
+ */
+public class IOPipe extends SocketIOPipe {
+
+    public static final byte PORTS_COUNT = 10;
+    public static final byte NO_PORTS = 0;
+
+    public static final String PIPE_LOG_PREFIX = "IOPipe> ";
+
+    private DebugeeProcess debugee;
+
+    /**
+      * Make <code>IOPipe</code> at debugee's side.
+      *
+      * @deprecated Use DebugeeArgumentHandler.createDebugeeIOPipe(Log) instead.
+      *
+      * @see DebugeeArgumentHandler#createDebugeeIOPipe(Log)
+      */
+    public IOPipe(DebugeeArgumentHandler argumentHandler, Log log) {
+        this(log, getTestHost(argumentHandler), argumentHandler.getPipePortNumber(),
+                (long)argumentHandler.getWaitTime() * 60 * 1000, false);
+    }
+
+    /**
+      * Make <code>IOPipe</code> at debugger's side
+      * with given <code>Debugee</code> mirror.
+      *
+      * @deprecated Use Debugee.createIOPipe() instead.
+      */
+    public IOPipe(DebugeeProcess debugee) {
+        this(debugee.getLog(),
+                debugee.getArgumentHandler().getDebugeeHost(),
+                debugee.getArgumentHandler().getPipePortNumber(),
+                (long)debugee.getArgumentHandler().getWaitTime() * 60 * 1000,
+                true);
+
+        this.debugee = debugee;
+    }
+
+    /**
+      * Make general <code>IOPipe</code> object with specified parameters.
+      */
+    protected IOPipe(Log log, String host, int port, long timeout, boolean listening) {
+        super("IOPipe", log, PIPE_LOG_PREFIX, host, port, timeout, listening);
+    }
+
+    protected void connect() {
+        if (listening) {
+            setServerSocket(debugee.getPipeServerSocket());
+            setConnectingProcess(debugee.getProcess());
+        }
+
+        super.connect();
+    }
+
+    /**
+     * Get appropriate test host name relying on the provided argumnets.
+     */
+    private static String getTestHost(DebugeeArgumentHandler argumentHandler) {
+        return argumentHandler.getTestHost();
+    }
+
+} // IOPipe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/SocketConnection.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,680 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.jpda;
+
+import java.io.*;
+import java.net.*;
+
+import nsk.share.*;
+
+/**
+ * This class implements basic connection channel via TCP/IP sockets.
+ */
+class BasicSocketConnection {
+
+    protected static int TRACE_LEVEL_PACKETS = 10;
+
+    protected static int TRACE_LEVEL_THREADS = 20;
+
+    protected static int TRACE_LEVEL_ACTIONS = 30;
+
+    protected static int TRACE_LEVEL_SOCKETS = 40;
+
+    protected static int TRACE_LEVEL_IO = 50;
+
+    protected String name = null;
+
+    protected ServerSocket serverSocket = null;
+
+    protected Socket socket = null;
+
+    protected InputStream sin = null;
+
+    protected OutputStream sout = null;
+
+    protected Process connectingProcess = null;
+
+    protected volatile boolean connected = false;
+
+    protected volatile boolean closed = false;
+
+    protected volatile boolean connectionClosed = false;
+
+    protected volatile boolean shouldStop = false;
+
+    protected Log.Logger logger = null;
+
+    /**
+     * Make an empty connection with specified name.
+     *
+     * @param logger
+     *                Logger object for printing log messages
+     * @param name
+     *                connection name
+     */
+    public BasicSocketConnection(Log.Logger logger, String name) {
+        this.logger = logger;
+        this.name = name;
+    }
+
+    /**
+     * Try to bind connection to the local port.
+     *
+     * @param port
+     *                port number to bind to
+     *
+     * @throws IOException
+     *                 if error occured while binding
+     */
+    protected void tryBind(int port) throws IOException {
+        logger.trace(TRACE_LEVEL_IO, "Binding for " + name + " connection to port: " + port);
+        serverSocket = new ServerSocket(port, 1);
+        logger.trace(TRACE_LEVEL_IO, "Bound for " + name + " connection to port: " + port);
+    }
+
+    /**
+     * Bind connection to the local port for specified timeout.
+     *
+     * @param port
+     *                port number to bind to
+     * @param timeout
+     *                binding timeout in milliseconds
+     *
+     * @throws Failure
+     *                 if error ocured while binding
+     */
+    protected void bind(int port, long timeout) {
+        BindException bindException = null;
+        long timeToFinish = System.currentTimeMillis() + timeout;
+        for (long i = 0; !shouldStop && (timeout == 0 || System.currentTimeMillis() < timeToFinish); i++) {
+            try {
+                tryBind(port);
+                return;
+            } catch (BindException e) {
+                bindException = e;
+                logger.display("Attempt #" + i + " to bind to port " + port + " failed:\n\t" + e);
+                try {
+                    Thread.sleep(DebugeeBinder.CONNECT_TRY_DELAY);
+                } catch (InterruptedException ie) {
+                    ie.printStackTrace(logger.getOutStream());
+                    throw new Failure("Thread interrupted while binding for " + name + " connection to port " + port + ":\n\t" + ie);
+                }
+            } catch (IOException e) {
+                e.printStackTrace(logger.getOutStream());
+                throw new Failure("Caught IOException while binding for " + name + " connection to port " + port + ":\n\t" + e);
+            }
+        }
+        throw new Failure("Unable to bind for " + name + " connection to port " + port + " for " + timeout + "ms timeout:\n\t" + bindException);
+    }
+
+    /**
+     * Accept connection at the bound port for specified timeout.
+     *
+     * @param timeout
+     *                accepting timeout in milliseconds
+     *
+     * @throws Failure
+     *                 if error occured while accepting connection
+     */
+    public void accept(long timeout) {
+        int port = serverSocket.getLocalPort();
+        logger.trace(TRACE_LEVEL_IO, "Listening for " + name + " connection at port: " + port);
+        socket = null;
+        try {
+            if (timeout > Integer.MAX_VALUE) {
+                throw new TestBug("Too large timeout long value: " + timeout + " (can't cast it to int)");
+            }
+
+            serverSocket.setSoTimeout((int)timeout);
+
+            long waitStartTime = System.currentTimeMillis();
+
+            /*
+             * We found that sometimes (very rarely) on Solaris ServerSocket.accept() throws InterruptedIOException
+             * even if connection timeout (specified through ServerSocket.setSoTimeout) didn't expire.
+             * Following code tries to catch such case and call ServerSocket.accept() while timeout didn't expire.
+             */
+            do {
+                try {
+                    socket = serverSocket.accept();
+                    logger.trace(TRACE_LEVEL_IO, "Accepted " + name + " connection at port: " + port);
+                } catch (InterruptedIOException e) {
+                    long interruptTime = System.currentTimeMillis();
+                    long waitTime = interruptTime - waitStartTime;
+
+                    logger.display("Caught InterruptedIOException. Wait start time: " + waitStartTime + ", exception was thrown at: "
+                            + interruptTime + ", wait time: " + (interruptTime - waitStartTime) + ", actual timeout: " + timeout);
+
+                    // if waitTime was too small call ServerSocket.accept() one more time
+                    if (!shouldStop && (waitTime < (timeout / 2))) {
+                        logger.display("InterruptedIOException was thrown too early, trying to call ServerSocket.accept() one more time");
+                        continue;
+                    } else {
+                        if (!shouldStop) {
+                            logger.complain("Caught InterruptedIOException while listening for " + name + " connection at port " + port + ":\n\t" + e);
+                            throw new Failure("Connection for " + name +
+                                    " at port " + port +
+                                    " wasn't accepted in " + timeout + "ms");
+                        } else {
+                            logger.display("Listening was interrupted (caught InterruptedIOException while listening for " + name + " connection at port " + port + ":\n\t" + e + ")");
+                            break;
+                        }
+                    }
+                }
+            } while (socket == null);
+
+        } catch (IOException e) {
+            if (!shouldStop) {
+                e.printStackTrace(logger.getOutStream());
+                throw new Failure("Caught IOException while listening for " + name + " connection at port " + port + ":\n\t" + e);
+            } else {
+                logger.display("Listening was interrupted (caught InterruptedIOException while listening for " + name + " connection at port " + port + ":\n\t" + e + ")");
+            }
+        } finally {
+            closeServerConnection();
+        }
+
+        if (!shouldStop) {
+            if (socket == null) {
+                throw new Failure("No " + name + " connection accepted at port " + port + " for " + timeout + "ms timeout");
+            }
+
+            onConnected();
+        }
+    }
+
+    /**
+     * Attach connection to the remote host and port.
+     *
+     * @param host
+     *                name of remote host to attach to
+     * @param port
+     *                port number to attach to
+     *
+     * @throws Failure
+     *                 if error occured while attaching
+     */
+    public void attach(String host, int port) {
+        try {
+            logger.trace(TRACE_LEVEL_IO, "Attaching for " + name + " connection to host: " + host + ":" + port);
+            socket = new Socket(host, port);
+            socket.setTcpNoDelay(true);
+            logger.trace(TRACE_LEVEL_IO, "Attached for " + name + " connection to host: " + host + ":" + port);
+        } catch (IOException e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught IOException while attaching for " + name + " connection to " + host + ":" + port + ":\n\t" + e);
+        }
+        if (!shouldStop) {
+            onConnected();
+        }
+    }
+
+    /**
+     * Continuously attach to the remote host for the specified timeout.
+     *
+     * @param host
+     *                name of remote host to attach to
+     * @param port
+     *                port number to attach to
+     * @param timeout
+     *                attaching timeout in milliseconds
+     *
+     * @throws Failure
+     *                 if error occured while attaching
+     */
+    public void continueAttach(String host, int port, long timeout) {
+        socket = null;
+        long timeToFinish = System.currentTimeMillis() + timeout;
+        ConnectException lastException = null;
+        logger.trace(TRACE_LEVEL_IO, "Attaching for " + name + " connection to host: " + host + ":" + port);
+        try {
+            for (long i = 0; !shouldStop && (timeout == 0 || System.currentTimeMillis() < timeToFinish); i++) {
+                try {
+                    socket = new Socket(host, port);
+                    logger.trace(TRACE_LEVEL_IO, "Attached for " + name + " connection to host: " + host + ":" + port);
+                    break;
+                } catch (ConnectException e) {
+                    logger.display("Attempt #" + i + " to attach for " + name + " connection failed:\n\t" + e);
+                    lastException = e;
+                    // check if listening process still alive
+                    if (!checkConnectingProcess()) {
+                        shouldStop = true;
+                        throw new Failure("Break attaching to " + name + " connection: " + "listening process exited");
+                    }
+                    // sleep between attempts
+                    try {
+                        Thread.sleep(DebugeeBinder.CONNECT_TRY_DELAY);
+                    } catch (InterruptedException ie) {
+                        throw new Failure("Thread interrupted while attaching for " + name + " connection to " + host + ":" + port + ":\n\t" + ie);
+                    }
+                }
+            }
+
+        } catch (IOException e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught IOException while attaching for " + name + " connection to " + host + ":" + port + ":\n\t" + e);
+        }
+
+        if (!shouldStop) {
+            if (socket == null) {
+                throw new Failure("Unable to attach for " + name + " connection to " + host + ":" + port + " for " + timeout + "ms timeout:\n\t"
+                        + lastException);
+            }
+
+            onConnected();
+        }
+    }
+
+    /**
+     * Set already bound serverSocket for further connection.
+     */
+    public void setServerSocket(ServerSocket serverSocket) {
+        this.serverSocket = serverSocket;
+    }
+
+    /**
+     * Set already connected socket for connection.
+     */
+    public void setSocket(Socket socket) {
+        this.socket = socket;
+        if (!shouldStop) {
+            onConnected();
+        }
+    }
+
+    /**
+     * Get socket of already established connection.
+     */
+    public Socket getSocket() {
+        return socket;
+    }
+
+    /**
+     * Return true if another connecting process is still alive.
+     */
+    public boolean checkConnectingProcess() {
+        if (connectingProcess == null) {
+            // no process to check
+            return true;
+        }
+        try {
+            int exitCode = connectingProcess.exitValue();
+        } catch (IllegalThreadStateException e) {
+            // process is still alive
+            return true;
+        }
+        // process exited
+        return false;
+    }
+
+    /**
+     * Set another connecting process to control if it is still alive.
+     */
+    public void setConnectingProcess(Process process) {
+        connectingProcess = process;
+    }
+
+    /**
+     * Check if connection is established.
+     */
+    public boolean isConnected() {
+        return connected;
+    }
+
+    /**
+     * Close socket and associated streams.
+     */
+    public void close() {
+        if (!closed) {
+            shouldStop = true;
+            closeConnection();
+            closed = true;
+        }
+    }
+
+    /**
+     * Send the specified byte throw the connection.
+     */
+    public void writeByte(byte b) throws IOException {
+        logger.trace(TRACE_LEVEL_IO, "Writing byte: " + b);
+        sout.write(b);
+        sout.flush();
+        logger.trace(TRACE_LEVEL_IO, "Wrote byte: " + b);
+    }
+
+    /**
+     * Read a byte and return it or -1.
+     */
+    public int readByte() throws IOException {
+        logger.trace(TRACE_LEVEL_IO, "Reading byte");
+        int b = sin.read();
+        logger.trace(TRACE_LEVEL_IO, "Received byte: " + b);
+        return b;
+    }
+
+    /**
+     * Perform some actions after connection established.
+     */
+    protected void onConnected() {
+        if (!shouldStop) {
+            setSocketOptions();
+            makeSocketStreams();
+            connected = true;
+        }
+    }
+
+    /**
+     * Set socket options after connection established.
+     */
+    protected void setSocketOptions() {
+    }
+
+    /**
+     * Close server socket.
+     */
+    protected void closeServerConnection() {
+        if (serverSocket != null) {
+            try {
+                serverSocket.close();
+                logger.trace(TRACE_LEVEL_IO, "ServerSocket closed: " + serverSocket);
+            } catch (IOException e) {
+                logger.display("# WARNING: " + "Caught IOException while closing ServerSocket of " + name + " connection:\n\t" + e);
+            }
+        }
+    }
+
+    /**
+     * Close socket of connection to remote host.
+     */
+    protected void closeHostConnection() {
+        if (socket != null) {
+            try {
+                socket.close();
+                logger.trace(TRACE_LEVEL_IO, "Socket closed: " + socket);
+            } catch (IOException e) {
+                logger.display("# WARNING: " + "Caught IOException while closing socket of " + name + " connection:\n\t" + e);
+            }
+        }
+    }
+
+    /**
+     * Close socket streams.
+     */
+    protected void closeSocketStreams() {
+        if (sout != null) {
+            try {
+                logger.trace(TRACE_LEVEL_IO, "Closing socket output stream: " + sout);
+                sout.close();
+                logger.trace(TRACE_LEVEL_IO, "Output stream closed: " + sout);
+            } catch (IOException e) {
+                logger.display("# WARNING: " + "Caught IOException while closing OutputStream of " + name + " connection:\n\t" + e);
+            }
+        }
+        if (sin != null) {
+            try {
+                logger.trace(TRACE_LEVEL_IO, "Closing socket input stream: " + sin);
+                sin.close();
+                logger.trace(TRACE_LEVEL_IO, "Input stream closed: " + sin);
+            } catch (IOException e) {
+                logger.display("# WARNING: " + "Caught IOException while closing InputStream of" + name + " connection:\n\t" + e);
+            }
+        }
+    }
+
+    /**
+     * Close sockets and associated streams.
+     */
+    protected void closeConnection() {
+        if (connectionClosed)
+            return;
+
+        logger.trace(TRACE_LEVEL_IO, "Closing " + name + " connection");
+        closeSocketStreams();
+        closeHostConnection();
+        closeServerConnection();
+        connectionClosed = true;
+    }
+
+    /**
+     * Make up socket streams after connection established.
+     */
+    protected void makeSocketStreams() {
+        try {
+            logger.trace(TRACE_LEVEL_IO, "Getting input/output socket streams for " + name + " connection");
+            sout = socket.getOutputStream();
+            logger.trace(TRACE_LEVEL_IO, "Got socket output stream: " + sout);
+            sin = socket.getInputStream();
+            logger.trace(TRACE_LEVEL_IO, "Got socket input stream: " + sin);
+        } catch (IOException e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught exception while making streams for " + name + " connection:\n\t" + e);
+        }
+    }
+
+} // BasicSocketConnection
+
+/**
+ * This class implements connection channel via TCP/IP sockets. After connection
+ * established special inner threads are started, which periodically test the
+ * connection by pinging each other. If ping timeout occurs connection is closed
+ * and any thread waiting for read from this connection gets exception.
+ *
+ * @see #setPingTimeout(long)
+ */
+public class SocketConnection extends BasicSocketConnection {
+
+    private static final long PING_INTERVAL = 1 * 1000; // milliseconds
+
+    private static byte DATA_BYTE = (byte) 0x03;
+
+    private static byte DISCONNECT_BYTE = (byte) 0x04;
+
+    private final Object inLock = new Object();
+    private ObjectInputStream in = null;
+
+    private final Object outLock = new Object();
+    private ObjectOutputStream out = null;
+
+    private volatile long pingTimeout = 0; // don't use ping
+
+    /**
+     * Make an empty connection with specified name.
+     *
+     * @param log
+     *                Log object for printing log messages
+     * @param name
+     *                connection name
+     */
+    public SocketConnection(Log log, String name) {
+        this(new Log.Logger(log, name + " connection> "), name);
+    }
+
+    /**
+     * Make an empty connection with specified name.
+     *
+     * @param logger
+     *                Logger object for printing log messages
+     * @param name
+     *                connection name
+     */
+    public SocketConnection(Log.Logger logger, String name) {
+        super(logger, name);
+    }
+
+    /**
+     * Set ping timeout in milliseconds (0 means don't use ping at all).
+     */
+    public void setPingTimeout(long timeout) {
+        logger.display("# WARNING: Setting ping timeout for " + name + " connection ingnored: " + timeout + " ms");
+        pingTimeout = timeout;
+    }
+
+    /**
+     * Returns value of current ping timeout in milliseconds (0 means ping is
+     * not used).
+     */
+    public long getPingTimeout() {
+        return pingTimeout;
+    }
+
+    /**
+     * Receive an object from remote host.
+     */
+    public Object readObject() {
+        if (!isConnected()) {
+            throw new Failure("Unable to read object from not established " + name + " connection");
+        }
+
+        try {
+            return doReadObject();
+        } catch (EOFException e) {
+            return null;
+        } catch (Exception e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught Exception while reading an object from " + name + " connection:\n\t" + e);
+        }
+    }
+
+    /**
+     * Send an object to remote host.
+     */
+    public void writeObject(Object object) {
+        if (!isConnected()) {
+            throw new Failure("Unable to send object throw not established " + name + " connection:\n\t" + object);
+        }
+
+        try {
+            doWriteObject(object);
+        } catch (IOException e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught IOException while writing an object to " + name + " connection:\n\t" + e);
+        }
+    }
+
+    /**
+     * Close socket and associated streams and finish all internal threads.
+     */
+    public void close() {
+        if (!closed) {
+            // disconnect();
+            shouldStop = true;
+            super.close();
+            closed = true;
+        }
+    }
+
+    /**
+     * Perform some actions after connection has established.
+     */
+    protected void onConnected() {
+        super.onConnected();
+    }
+
+    /**
+     * Do write an object to the connection channel.
+     */
+    private void doWriteObject(Object object) throws IOException {
+        logger.trace(TRACE_LEVEL_IO, "writing object: " + object);
+        synchronized(outLock) {
+            out.writeObject(object);
+            out.flush();
+        }
+        logger.trace(TRACE_LEVEL_PACKETS, "* sent: " + object);
+    }
+
+    /**
+     * Do read an object from the connection channel.
+     */
+    private Object doReadObject() throws IOException, ClassNotFoundException {
+        logger.trace(TRACE_LEVEL_IO, "Reading object");
+        Object object = null;
+        synchronized(inLock) {
+            object = in.readObject();
+        }
+        logger.trace(TRACE_LEVEL_PACKETS, "* recv: " + object);
+        return object;
+    }
+
+    /**
+     * Close socket streams.
+     */
+    protected void closeSocketStreams() {
+        synchronized(outLock) {
+            if (out != null) {
+                try {
+                    logger.trace(TRACE_LEVEL_IO, "Closing socket output stream: " + out);
+                    out.close();
+                    logger.trace(TRACE_LEVEL_IO, "Output stream closed: " + out);
+                } catch (IOException e) {
+                    logger.display("# WARNING: " + "Caught IOException while closing ObjectOutputStream of " + name + " connection:\n\t" + e);
+                }
+            }
+        }
+        synchronized(inLock) {
+            if (in != null) {
+                try {
+                    logger.trace(TRACE_LEVEL_IO, "Closing socket input stream: " + in);
+                    in.close();
+                    logger.trace(TRACE_LEVEL_IO, "Input stream closed: " + in);
+                } catch (IOException e) {
+                    logger.display("# WARNING: " + "Caught IOException while closing ObjectInputStream of" + name + " connection:\n\t" + e);
+                }
+            }
+        }
+        super.closeSocketStreams();
+    }
+
+    /**
+     * Close sockets and associated streams.
+     */
+    protected void closeConnection() {
+        if (connectionClosed)
+            return;
+        connected = false;
+        shouldStop = true;
+        super.closeConnection();
+    }
+
+    /**
+     * Make up object streams for socket.
+     */
+    protected void makeSocketStreams() {
+        try {
+            logger.trace(TRACE_LEVEL_IO, "Making input/output object streams for " + name + " connection");
+            synchronized(outLock) {
+                out = new ObjectOutputStream(socket.getOutputStream());
+                out.flush();
+            }
+            logger.trace(TRACE_LEVEL_IO, "Output stream created: " + out);
+            synchronized(inLock) {
+                in = new ObjectInputStream(socket.getInputStream());
+            }
+            logger.trace(TRACE_LEVEL_IO, "Input stream created: " + in);
+        } catch (IOException e) {
+            e.printStackTrace(logger.getOutStream());
+            throw new Failure("Caught exception while making streams for " + name + " connection:\n\t" + e);
+        }
+    }
+
+} // SocketConnection
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/SocketIOPipe.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jpda;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import nsk.share.*;
+
+/*
+ * This class represents communication channel based on TCP/IP sockets.
+ * Usage of this class implies creation of objects of 2 types: server SocketIOPipe object
+ * (this object creates server socket and waits for incoming connection) and client
+ * SocketIOPipe (this object attaches to server).
+ *
+ * Server and client objects should be created using special static methods provided by this class,
+ * for example 'createServerIOPipe(Log log, int port, long timeout)' for server SocketIOPipe
+ * and 'createClientIOPipe(Log log, String host, int port, long timeout)' for client SocketIOPipe.
+ *
+ * When SocketIOPipe is created it can be used to send and receive strings using methods 'readln()' and 'println(String s)'.
+ * TCP/IP connection is established at the first attempt to read or write data.
+ *
+ * For example, if client process should send string 'OK' to the server process which is run
+ * at the host 'SERVER_HOST' following code can be written:
+ *
+ * Server side:
+ *
+ *  // SocketIOPipe creates ServerSocket listening given port
+ *  SocketIOPipe pipe = SocketIOPipe.createServerIOPipe(log, port, timeoutValue);
+ *
+ *  // SocketIOPipe waits connection from client and reads data sent by the client
+ *  String command = pipe.readln();
+ *
+ * Client side:
+ *
+ *  // initialize SocketIOPipe with given values of server host name and port
+ *  SocketIOPipe pipe = SocketIOPipe.createClientIOPipe(log, 'SERVER_HOST', port, timeoutValue);
+ *
+ *  String command = "OK";
+ *  // SocketIOPipe tries to create socket and send command to the server
+ *  pipe.println(command);
+ *
+ */
+public class SocketIOPipe extends Log.Logger implements Finalizable {
+
+    public static final int DEFAULT_TIMEOUT_VALUE = 1 * 60 * 1000;
+
+    public static final String DEFAULT_PIPE_LOG_PREFIX = "SocketIOPipe> ";
+
+    protected boolean listening;
+
+    protected String host;
+
+    protected int port;
+
+    protected long timeout;
+
+    protected SocketConnection connection;
+
+    protected volatile boolean shouldStop;
+
+    protected Process connectingProcess;
+
+    protected ServerSocket serverSocket;
+
+    protected String name;
+
+    /**
+     * Make general <code>IOPipe</code> object with specified parameters.
+     */
+    protected SocketIOPipe(String name, Log log, String logPrefix, String host, int port, long timeout, boolean listening) {
+        super(log, logPrefix);
+        this.host = host;
+        this.port = port;
+        this.timeout = timeout;
+        this.listening = listening;
+        this.name = name;
+    }
+
+    /**
+     * Make general <code>IOPipe</code> object with specified parameters.
+     */
+    protected SocketIOPipe(Log log, String logPrefix, String host, int port, long timeout, boolean listening) {
+        super(log, logPrefix);
+        this.host = host;
+        this.port = port;
+        this.timeout = timeout;
+        this.listening = listening;
+    }
+
+    /**
+     *  Create listening SocketIOPipe using given port
+     */
+    public static SocketIOPipe createServerIOPipe(Log log, int port, long timeout) {
+        SocketIOPipe pipe = new SocketIOPipe(log, DEFAULT_PIPE_LOG_PREFIX, null, 0, timeout, true);
+
+        try {
+            ServerSocket ss = new ServerSocket();
+            if (port == 0) {
+              // Only need SO_REUSEADDR if we're using a fixed port. If we
+              // start seeing EADDRINUSE due to collisions in free ports
+              // then we should retry the bind() a few times.
+              ss.setReuseAddress(false);
+            }
+            ss.bind(new InetSocketAddress(port));
+            pipe.setServerSocket(ss);
+        } catch (IOException e) {
+            e.printStackTrace(log.getOutStream());
+            throw new Failure("Caught IOException while binding for IOPipe connection: \n\t" + e);
+        }
+
+        return pipe;
+    }
+
+    /**
+     *  Create listening SocketIOPipe using any free port
+     */
+    public static SocketIOPipe createServerIOPipe(Log log, long timeout) {
+        return createServerIOPipe(log, 0, timeout);
+    }
+
+    /**
+     *  Create attaching SocketIOPipe using given port and timeout
+     */
+    public static SocketIOPipe createClientIOPipe(Log log, String host, int port, long timeout) {
+        return new SocketIOPipe(log, DEFAULT_PIPE_LOG_PREFIX, host, port, timeout, false);
+    }
+
+    /**
+     * Return true if <code>IOPipe</code> connection established.
+     */
+    public boolean isConnected() {
+        return (connection != null && connection.isConnected());
+    }
+
+    /**
+     * Returns port number used by SocketIOPipe
+     */
+    public int getPort() {
+        return port;
+    }
+
+    protected void setConnectingProcess(Process connectingProcess) {
+        this.connectingProcess = connectingProcess;
+    }
+
+    protected void setServerSocket(ServerSocket serverSocket) {
+        this.serverSocket = serverSocket;
+        if (serverSocket != null)
+            port = serverSocket.getLocalPort();
+    }
+
+    /**
+     * Write (and flush) given <code>line</code> to this
+     * <code>IOPipe</code> cnannel.
+     *
+     * @throws Failure if error occured while sending data
+     */
+    public void println(String line) {
+        if (connection == null) {
+            connect();
+        }
+        connection.writeObject(line);
+    }
+
+    /**
+     * Read a text line from this <code>IOPipe</code> channel,
+     * or return <i>null</i> if EOF reached.
+     *
+     * @throws Failure if error occured while reading data
+     */
+    public String readln() {
+        if (connection == null) {
+            connect();
+        }
+        String line = (String) connection.readObject();
+        return line;
+    }
+
+    /**
+     * Close this <code>IOPipe</code> connection.
+     */
+    public void close() {
+        shouldStop = true;
+        if (connection != null) {
+            connection.close();
+        }
+    }
+
+    /**
+     * Establish <code>IOPipe</code> connection by attaching or accepting
+     * connection appropriately.
+     */
+    protected void connect() {
+        if (connection != null) {
+            throw new TestBug("IOPipe connection is already established");
+        }
+
+        if (shouldStop)
+            return;
+
+        connection = new SocketConnection(this, getName());
+
+        if (listening) {
+            connection.setConnectingProcess(connectingProcess);
+            if (serverSocket == null) {
+                connection.bind(port, timeout);
+            } else {
+                connection.setServerSocket(serverSocket);
+            }
+
+            if (shouldStop)
+                return;
+
+            // wait for connection from remote host
+            connection.accept(timeout);
+
+        } else {
+            // attach from the debuggee's side
+            connection.continueAttach(host, port, timeout);
+        }
+    }
+
+    /**
+     * Set ping timeout in milliseconds (0 means don't use ping at all).
+     */
+    public void setPingTimeout(long timeout) {
+        if (connection == null) {
+            throw new TestBug("Attempt to set ping timeout for not established connection");
+        }
+        connection.setPingTimeout(timeout);
+    }
+
+    /**
+     * Returns value of current ping timeout in milliseconds (0 means ping is not used).
+     */
+    public long getPingTimeout() {
+        if (connection == null) {
+            throw new TestBug("Attempt to get ping timeout for not established connection");
+        }
+        return connection.getPingTimeout();
+    }
+
+    /**
+     * Perform finalization of the object by invoking close().
+     */
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+
+    /**
+     * Perform finalization of the object at exit by invoking finalize().
+     */
+    public void finalizeAtExit() throws Throwable {
+        finalize();
+    }
+
+    /**
+     * Field 'pipeCounter' and method 'getNextPipeNumber' are used to construct unique names for SocketIOPipes
+     */
+    private static int pipeCounter;
+
+    private synchronized int getNextPipeNumber() {
+        return pipeCounter++;
+    }
+
+    /**
+     * Construct name for SocketIOPipe if it wasn't specified
+     */
+    private String getName() {
+        if (name == null) {
+            name = "SocketIOPipe-" + getNextPipeNumber();
+        }
+
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/StateTestThread.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.jpda;
+
+import nsk.share.TestBug;
+import nsk.share.locks.MonitorLockingThread;
+
+/*
+ *  StateTestThread sequentially switches its state in following order:
+ *  - thread not started
+ *  - thread is running
+ *  - thread is sleeping
+ *  - thread in Object.wait()
+ *  - thread wait on java monitor
+ *  - thread is finished
+ *
+ *  To use this class create new instance of StateTestThread and sequentially call method nextState().
+ */
+public class StateTestThread extends Thread {
+    // thread states available through ThreadReference.state()
+    public static String stateTestThreadStates[] = { "UNKNOWN", "RUNNING", "SLEEPING", "WAIT", "MONITOR", "ZOMBIE" };
+
+    private Object waitOnObject = new Object();
+
+    public StateTestThread(String name) {
+        super(name);
+    }
+
+    private volatile boolean isRunning;
+
+    private volatile boolean waitState;
+
+    public int getCurrentState() {
+        return currentState;
+    }
+
+    private MonitorLockingThread auxiliaryThread = new MonitorLockingThread(this);
+
+    private boolean isExecutedWithErrors;
+
+    private volatile boolean readyToBeBlocked;
+
+    private String errorMessage;
+
+    public void run() {
+        isRunning = true;
+
+        // running state
+        while (isRunning)
+            ;
+
+        try {
+            // sleeping state
+            sleep(Long.MAX_VALUE);
+        } catch (InterruptedException e) {
+            // expected exception
+        }
+
+        synchronized (waitOnObject) {
+            try {
+                // wait state
+                while (waitState)
+                    waitOnObject.wait();
+            } catch (InterruptedException e) {
+                isExecutedWithErrors = true;
+                errorMessage = "StateTestThread was unexpected interrupted during waiting";
+            }
+        }
+
+        // start auxiliary thread which should acquire 'this' lock
+        auxiliaryThread.acquireLock();
+
+        readyToBeBlocked = true;
+
+        // try acquire the same lock as auxiliaryThread, switch state to 'wait on monitor'
+        synchronized (this) {
+
+        }
+    }
+
+    private int currentState = 1;
+
+    public void nextState() {
+        // check is thread states change as expected
+        if (isExecutedWithErrors)
+            throw new TestBug(errorMessage);
+
+        switch (currentState++) {
+        case 1:
+            // start thread
+            start();
+
+            while (!isRunning)
+                yield();
+
+            break;
+        case 2:
+            // stop running
+            isRunning = false;
+
+            while (this.getState() != Thread.State.TIMED_WAITING)
+                yield();
+
+            break;
+        case 3:
+            waitState = true;
+
+            // stop sleeping
+            interrupt();
+
+            while (getState() != Thread.State.WAITING)
+                yield();
+
+            break;
+        case 4:
+            waitState = false;
+
+            // stop wait
+            synchronized (waitOnObject) {
+                waitOnObject.notify();
+            }
+
+            while (!readyToBeBlocked || (getState() != Thread.State.BLOCKED))
+                yield();
+
+            break;
+        case 5:
+            // let StateTestThread thread acquire lock
+            auxiliaryThread.releaseLock();
+            try {
+                join();
+            } catch (InterruptedException e) {
+                throw new TestBug("Unexpected exception: " + e);
+            }
+            break;
+
+        default:
+            throw new TestBug("Invalid thread state");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import nsk.share.*;
+
+/*
+ * DeadlockLocker - class used for deadlock creation
+ *
+ * To create deadlock second 'inner' instance of DeadlockLocker is required.
+ *
+ * Deadlock creation scenario:
+ *      - object acquires its resource
+ *      - notify 'inner' through Wicket step1 that resource is locked and 'inner' can try to acquire this object's resource
+ *      - wait notification through Wicket step2 from 'inner' that 'inner' acquired its resource
+ *      - call readyWicket.unlock to notify thread waiting deadlock creation
+ *      - try acquire locked inner's resource, at the same time inner trying to acquire locked this object's resource - deadlock is created
+ *
+ * Subclasses should implement method doLock() taking in account described scenario.
+ *
+ *  Objects of DeadlockLocker should not be created directly, to create deadlocked threads use class DeadlockMaker
+ */
+abstract public class DeadlockLocker {
+    protected DeadlockLocker inner;
+
+    protected Wicket step1;
+
+    protected Wicket step2;
+
+    // 'readyWicket' is used to notify DeadlockMacker that deadlock is almost created
+    protected Wicket readyWicket;
+
+    public DeadlockLocker(Wicket step1, Wicket step2, Wicket readyWicket) {
+        this.step1 = step1;
+        this.step2 = step2;
+        this.readyWicket = readyWicket;
+    }
+
+    public void setInner(DeadlockLocker inner) {
+        this.inner = inner;
+    }
+
+    protected void checkInnerLocker() {
+        if (inner == null) {
+            throw new IllegalStateException(getClass().getName() + " deadlockLocker's inner locker is null");
+        }
+    }
+
+    protected abstract void doLock();
+
+    abstract public Object getLock();
+
+    private int lockCount;
+
+    final public void lock() {
+        // call this method once
+        if (lockCount++ > 1)
+            return;
+
+        // check that inner locker was set
+        checkInnerLocker();
+
+        doLock();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockMaker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import java.util.*;
+import nsk.share.TestBug;
+import nsk.share.Wicket;
+
+/*
+ * Class used to create deadlocked threads. It is possible create 2 or more deadlocked thread, also
+ * is is possible to specify resource of which type should lock each deadlocked thread
+ */
+public class DeadlockMaker {
+    // create deadlock with 2 threads
+    // lockType1 and lockType2 - type of locking resources used for deadlock creation
+    public static DeadlockedThread[] createDeadlockedThreads(LockType lockType1, LockType lockType2) {
+        DeadlockedThread[] resultThreads = new DeadlockedThread[2];
+
+        Wicket step1 = new Wicket();
+        Wicket step2 = new Wicket();
+
+        Wicket readyWicket = new Wicket(2);
+
+        DeadlockLocker locker1 = createLocker(lockType1, step1, step2, readyWicket);
+        DeadlockLocker locker2 = createLocker(lockType2, step2, step1, readyWicket);
+        locker1.setInner(locker2);
+        locker2.setInner(locker1);
+
+        resultThreads[0] = new DeadlockedThread(locker1);
+        resultThreads[1] = new DeadlockedThread(locker2);
+
+        resultThreads[0].start();
+        resultThreads[1].start();
+
+        readyWicket.waitFor();
+
+        // additional check to be sure that all threads really blocked
+        waitForDeadlock(resultThreads);
+
+        return resultThreads;
+    }
+
+    // create deadlock with several threads
+    // locksTypes - type of locking resources used for deadlock creation
+    public static DeadlockedThread[] createDeadlockedThreads(List<LockType> locksTypes) {
+        if (locksTypes.size() < 2) {
+            throw new IllegalArgumentException("Need at least 2 threads for deadlock");
+        }
+
+        int threadsNumber = locksTypes.size();
+
+        DeadlockedThread[] resultThreads = new DeadlockedThread[threadsNumber];
+
+        Wicket readyWicket = new Wicket(threadsNumber);
+
+        DeadlockLocker deadlockLockers[] = new DeadlockLocker[threadsNumber];
+        Wicket stepWickets[] = new Wicket[threadsNumber];
+
+        for (int i = 0; i < threadsNumber; i++)
+            stepWickets[i] = new Wicket();
+
+        int index1 = 0;
+        int index2 = 1;
+        for (int i = 0; i < threadsNumber; i++) {
+            Wicket step1 = stepWickets[index1];
+            Wicket step2 = stepWickets[index2];
+
+            deadlockLockers[i] = createLocker(locksTypes.get(i), step1, step2, readyWicket);
+
+            if (i > 0)
+                deadlockLockers[i - 1].setInner(deadlockLockers[i]);
+
+            index1 = (index1 + 1) % threadsNumber;
+            index2 = (index2 + 1) % threadsNumber;
+        }
+        deadlockLockers[threadsNumber - 1].setInner(deadlockLockers[0]);
+
+        for (int i = 0; i < threadsNumber; i++) {
+            resultThreads[i] = new DeadlockedThread(deadlockLockers[i]);
+            resultThreads[i].start();
+        }
+
+        readyWicket.waitFor();
+
+        // additional check to be sure that all threads really blocked
+        waitForDeadlock(resultThreads);
+
+        return resultThreads;
+    }
+
+    /*
+     * Wait when thread state will change to be sure that deadlock is really created
+     */
+    static private void waitForDeadlock(DeadlockedThread[] threads) {
+        Set<Thread.State> targetStates = new HashSet<Thread.State>();
+
+        // thread is waiting for a monitor lock to enter a synchronized block/method
+        targetStates.add(Thread.State.BLOCKED);
+
+        // thread calls LockSupport.park
+        targetStates.add(Thread.State.WAITING);
+
+        // thread calls LockSupport.parkNanos or LockSupport.parkUntil
+        targetStates.add(Thread.State.TIMED_WAITING);
+
+        for (Thread thread : threads) {
+            while (!targetStates.contains(thread.getState())) {
+                sleep(100);
+            }
+        }
+    }
+
+    static private void sleep(long millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {
+            System.out.println("Unexpected exception: " + e);
+            e.printStackTrace(System.out);
+
+            TestBug testBugException = new TestBug("Unexpected exception was throw: " + e);
+            testBugException.initCause(e);
+            throw testBugException;
+        }
+    }
+
+    // create locker with given type
+    public static DeadlockLocker createLocker(LockType type, Wicket step1, Wicket step2, Wicket readyWicket) {
+        switch (type) {
+        case SYNCHRONIZED_METHOD:
+            return new SynchronizedMethodLocker(step1, step2, readyWicket);
+        case SYNCHRONIZED_BLOCK:
+            return new SynchronizedBlockLocker(step1, step2, readyWicket);
+        case REENTRANT_LOCK:
+            return new ReentrantLockLocker(step1, step2, readyWicket);
+        case JNI_LOCK:
+            return new JNIMonitorLocker(step1, step2, readyWicket);
+        }
+
+        throw new IllegalArgumentException("Unsupported lock type: " + type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/DeadlockedThread.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import nsk.share.Wicket;
+
+/*
+ *  Thread class used for deadlock creation, requires instance of DeadlockLocker to created deadlock.
+ *  Objects of DeadlockedThread should not be created directly, to create deadlocked threads
+ *  use class DeadlockMaker
+ */
+public class DeadlockedThread extends Thread {
+    private DeadlockLocker locker;
+
+    private Wicket dedlockResolutionWicket = new Wicket();
+
+    // should call readyWicket.unlock() when deadlock is ready
+    public DeadlockedThread(DeadlockLocker locker) {
+        this.locker = locker;
+    }
+
+    public void run() {
+        locker.lock();
+
+        // reach here if deadlock was resolved
+        dedlockResolutionWicket.unlockAll();
+
+        // sleep if deadlock was resolved
+        try {
+            sleep(Long.MAX_VALUE);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
+    // If it is expected that deadlock with using of this DeadlockedThread should be resolved
+    // this method can be used for waiting this event
+    public void waitDeadlockResolution() {
+        // if deadlock was resolved DeadlockedThread calls dedlockResolutionWicket.unlockAll()
+        dedlockResolutionWicket.waitFor();
+    }
+
+    public DeadlockLocker getLocker() {
+        return locker;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/JNIMonitorLocker.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "jni.h"
+#include "nsk_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_PTR
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG_2(x, y) y
+#define JNI_ENV_ARG_3(x, y, z) y, z
+#define JNI_ENV_ARG_4(x, y, z. a) y, z, a
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG_2(x,y) x, y
+#define JNI_ENV_ARG_3(x, y, z) x, y, z
+#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+JNIEXPORT void JNICALL
+Java_nsk_share_locks_JNIMonitorLocker_doLock(JNIEnv *env, jobject thisObject)
+{
+/*
+This method executes JNI analog for following Java code:
+
+        JNI_MonitorEnter(this);
+
+        step1.unlockAll();
+        step2.waitFor();
+        readyWicket.unlock();
+        inner.lock();
+
+        JNI_MonitorExit(this);
+*/
+        jint success;
+        jfieldID field;
+        jclass thisObjectClass;
+
+        // fields 'step1' and 'step2'
+        jobject wicketObject;
+
+        // class for fields 'step1', 'step2', 'readyWicket'
+        jclass wicketClass;
+
+        // field 'inner'
+        jobject innerObject;
+
+        // class for field 'inner'
+        jclass deadlockLockerClass;
+
+        success = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero"));
+        }
+
+        thisObjectClass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject));
+
+        // step1.unlockAll()
+        field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, thisObjectClass, "step1", "Lnsk/share/Wicket;"));
+
+        wicketObject = JNI_ENV_PTR(env)->GetObjectField(JNI_ENV_ARG_3(env, thisObject, field));
+        wicketClass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, wicketObject));
+
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, wicketObject, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, wicketClass, "unlockAll", "()V"))));
+
+        // step2.waitFor()
+        field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, thisObjectClass, "step2", "Lnsk/share/Wicket;"));
+        wicketObject = JNI_ENV_PTR(env)->GetObjectField(JNI_ENV_ARG_3(env, thisObject, field));
+
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, wicketObject, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, wicketClass, "waitFor", "()V"))));
+
+        // readyWicket.unlock()
+        field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, thisObjectClass, "readyWicket", "Lnsk/share/Wicket;"));
+        wicketObject = JNI_ENV_PTR(env)->GetObjectField(JNI_ENV_ARG_3(env, thisObject, field));
+
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, wicketObject, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, wicketClass, "unlock", "()V"))));
+
+        // inner.lock()
+        field = JNI_ENV_PTR(env)->GetFieldID(JNI_ENV_ARG_4(env, thisObjectClass, "inner", "Lnsk/share/locks/DeadlockLocker;"));
+        innerObject = JNI_ENV_PTR(env)->GetObjectField(JNI_ENV_ARG_3(env, thisObject, field));
+        deadlockLockerClass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, innerObject));
+
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, innerObject, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, deadlockLockerClass, "lock", "()V"))));
+
+        success = JNI_ENV_PTR(env)->MonitorExit(JNI_ENV_ARG_2(env, thisObject));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorExit return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorExit return non-zero"));
+        }
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/JNIMonitorLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import nsk.share.Consts;
+import nsk.share.Wicket;
+
+/*
+ *  Class used for deadlock creation, acquires lock using JNI MonitorEnter
+ */
+public class JNIMonitorLocker extends DeadlockLocker {
+    static {
+        try {
+            System.loadLibrary("JNIMonitorLocker");
+        } catch (UnsatisfiedLinkError e) {
+            System.out.println("Unexpected UnsatisfiedLinkError on loading library 'JNIMonitorLocker'");
+            e.printStackTrace(System.out);
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+    }
+
+    public JNIMonitorLocker(Wicket step1, Wicket step2, Wicket readyWicket) {
+        super(step1, step2, readyWicket);
+    }
+
+    public Object getLock() {
+        return this;
+    }
+
+    protected native void doLock();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockType.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+/*
+ *  Types of resources used for deadlock creation
+ */
+public enum LockType
+{
+    SYNCHRONIZED_METHOD,
+    SYNCHRONIZED_BLOCK,
+    REENTRANT_LOCK,
+    JNI_LOCK
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockingThread.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "jni.h"
+#include "nsk_tools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_PTR
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG_2(x, y) y
+#define JNI_ENV_ARG_3(x, y, z) y, z
+#define JNI_ENV_ARG_4(x, y, z, a) y, z, a
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG_2(x,y) x, y
+#define JNI_ENV_ARG_3(x, y, z) x, y, z
+#define JNI_ENV_ARG_4(x, y, z, a) x, y, z, a
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+JNIEXPORT void JNICALL
+Java_nsk_share_locks_LockingThread_nativeJNIMonitorEnter(JNIEnv *env, jobject thisObject, jobject object)
+{
+        jint success;
+        jclass klass;
+
+        success  = JNI_ENV_PTR(env)->MonitorEnter(JNI_ENV_ARG_2(env, object));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorEnter return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorEnter return non-zero"));
+        }
+
+        klass = JNI_ENV_PTR(env)->GetObjectClass(JNI_ENV_ARG_2(env, thisObject));
+
+        JNI_ENV_PTR(env)->CallVoidMethod(JNI_ENV_ARG_3(env, thisObject, JNI_ENV_PTR(env)->GetMethodID(JNI_ENV_ARG_4(env, klass, "createStackFrame", "()V"))));
+
+        success  = JNI_ENV_PTR(env)->MonitorExit(JNI_ENV_ARG_2(env, object));
+
+        if(success != 0)
+        {
+                NSK_COMPLAIN1("MonitorExit return non-zero: %d\n", success);
+
+                JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG_3(env, JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG_2(env, "nsk/share/TestJNIError")), "MonitorExit return non-zero"));
+        }
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/LockingThread.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import java.util.*;
+import java.util.concurrent.locks.ReentrantLock;
+
+import nsk.share.Consts;
+import nsk.share.Log;
+import nsk.share.TestBug;
+import nsk.share.TestJNIError;
+import nsk.share.Wicket;
+
+/*
+ Thread with possibility acquiring monitors in different ways:
+ - entering synchronized method
+ - entering synchronized method for thread object itself
+ - entering synchronized static method
+ - entering synchronized method for thread class itself
+ - entering synchronized block on non-static object
+ - entering synchronized block on non-static on thread object itself
+ - entering synchronized block on static object
+ - entering synchronized block on static thread object itself
+ - JNI MonitorEnter.
+
+ Description of required thread stack should be passed to LockingThread in constructor.
+ When started locking thread create required stack and sleep until not interrupted.
+
+ LockingThread can relinquish acquired monitors in follows ways:
+ - relinquish single monitor through Object.wait - relinquishMonitor(int monitorIndex),
+ - relinquish single monitor through exiting from synchronized blocks/methods or through JNI MonitorExit  - exitSingleFrame(),
+ - relinquish all monitors(exit from all synchronized blocks/methods) - stopLockingThread()
+
+ Debug information about each acquired/relinquished monitor is stored and can be obtained through getMonitorsInfo().
+
+ To be sure that LockingThread have reached required state call method LockingThread.waitState().
+
+ Usage example:
+
+ List<String> stackFramesDescription = new ArrayList<String>();
+ stackFramesDescription.add(LockingThread.SYNCHRONIZED_METHOD);
+ stackFramesDescription.add(LockingThread.SYNCHRONIZED_OBJECT_BLOCK);
+
+ LockingThread lockingThread = new LockingThread(log, stackFramesDescription);
+
+ lockingThread.start();
+
+ // after calling waitState() LockingThread should complete stack creation
+  lockingThread.waitState();
+
+  lockingThread.exitSingleFrame();
+
+  // after calling waitState() LockingThread should complete exit from stack frame
+   lockingThread.waitState();
+   */
+public class LockingThread extends Thread {
+    // native part uses TestJNIError class
+    private static final Class<?> jniErrorKlass = TestJNIError.class;
+    static {
+        try {
+            System.loadLibrary("LockingThread");
+        } catch (UnsatisfiedLinkError e) {
+            System.out.println("Unexpected UnsatisfiedLinkError on loading library 'LockingThread'");
+            e.printStackTrace(System.out);
+            System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_FAILED);
+        }
+    }
+
+    /*
+     *  Information about acquired monitor
+     */
+    public static class DebugMonitorInfo {
+        public DebugMonitorInfo(Object monitor, int stackDepth, Thread thread, boolean isNative) {
+            this.monitor = monitor;
+            this.stackDepth = stackDepth;
+            this.thread = thread;
+            this.isNative = isNative;
+        }
+
+        public Object monitor;
+
+        public int stackDepth;
+
+        public Thread thread;
+
+        boolean isNative;
+    }
+
+    // acquire JNI monitor through JNIMonitorEnter()
+    public static final String JNI_MONITOR_ENTER = "JNI_MONITOR_ENTER";
+
+    // entering synchronized static method
+    public static final String SYNCHRONIZED_STATIC_METHOD = "SYNCHRONIZED_STATIC_METHOD";
+
+    // entering synchronized static method for thread class itself
+    public static final String SYNCHRONIZED_STATIC_THREAD_METHOD = "SYNCHRONIZED_STATIC_THREAD_METHOD";
+
+    // entering synchronized method
+    public static final String SYNCHRONIZED_METHOD = "SYNCHRONIZED_METHOD";
+
+    // entering synchronized method for thread object itself
+    public static final String SYNCHRONIZED_THREAD_METHOD = "SYNCHRONIZED_THREAD_METHOD";
+
+    // entering synchronized block for thread object itself
+    public static final String SYNCHRONIZED_THIS_BLOCK = "SYNCHRONIZED_THIS_BLOCK";
+
+    // entering synchronized block
+    public static final String SYNCHRONIZED_OBJECT_BLOCK = "SYNCHRONIZED_OBJECT_BLOCK";
+
+    // entering synchronized block on static object
+    public static final String SYNCHRONIZED_BLOCK_STATIC_OBJECT = "SYNCHRONIZED_BLOCK_STATIC_OBJECT";
+
+    // entering synchronized block on static thread object itself
+    public static final String SYNCHRONIZED_BLOCK_STATIC_THREAD_OBJECT = "SYNCHRONIZED_BLOCK_STATIC_THREAD_OBJECT";
+
+    // entering frame without monitor acquiring
+    public static final String FRAME_WITHOUT_LOCK = "FRAME_WITHOUT_LOCK";
+
+    // all acquired monitors
+    private List<DebugMonitorInfo> monitorsInfo = new ArrayList<DebugMonitorInfo>();
+
+    // This parameter should be passed in constructor
+    // It describe how many locks and in which way LockingThread should acquire
+    private List<String> stackFramesDescription;
+
+    private Log log;
+
+    // is during LockingThread's operations any errors occurred
+    private boolean executedWithErrors;
+
+    public boolean isExecutedWithErrors() {
+        return executedWithErrors;
+    }
+
+    public LockingThread(Log log, List<String> stackFramesDescription) {
+        this.log = log;
+        this.stackFramesDescription = stackFramesDescription;
+    }
+
+    // return array containing all acquired monitors
+    public DebugMonitorInfo[] getMonitorsInfo(boolean returnJNIMonitors) {
+        Map<Object, DebugMonitorInfo> result = new HashMap<Object, DebugMonitorInfo>();
+
+        for (int i = monitorsInfo.size() - 1; i >= 0; i--) {
+            DebugMonitorInfo monitorInfo = monitorsInfo.get(i);
+
+            if ((returnJNIMonitors || !monitorInfo.isNative) &&
+
+            // don't return relinquished monitors
+                    (monitorInfo.monitor != relinquishedMonitor) &&
+
+                    // return only last monitor occurrence
+                    !result.containsKey(monitorInfo.monitor)) {
+                result.put(monitorInfo.monitor, monitorInfo);
+            }
+        }
+
+        return result.values().toArray(new DebugMonitorInfo[] {});
+    }
+
+    void log(String message) {
+        log.display(Thread.currentThread().getName() + ": " + message);
+    }
+
+    // add debug information about acquired monitor
+    void addMonitorInfo(DebugMonitorInfo monitorInfo) {
+        monitorsInfo.add(monitorInfo);
+    }
+
+    // remove debug information about acquired monitor (also should update information about stack depth)
+    void removeMonitorInfo(DebugMonitorInfo removedMonitor) {
+        for (DebugMonitorInfo monitor : monitorsInfo) {
+            if (monitor.stackDepth > removedMonitor.stackDepth)
+                monitor.stackDepth -= 2;
+        }
+
+        monitorsInfo.remove(removedMonitor);
+    }
+
+    // used for stack frames creation
+    private int currentIndex;
+
+    // Recursive function used for stack frames creation
+
+    // For example if LockingThread should acquire 1 monitor through synchronized block
+    // and 1 monitor through synchronized method pass list with values SYNCHRONIZED_METHOD and SYNCHRONIZED_OBJECT_BLOCK
+    // to the constructor and after running LockingThread will have following stack frames:
+
+    // run()
+    //  createStackFrame()
+    //      ClassWithSynchronizedMethods().synchronizedMethod() // monitor for instance of ClassWithSynchronizedMethods is acquired here
+    //          createStackFrame()
+    //              synchronizedObjectBlock()   // monitor for instance of Object is acquired here
+    //                  createStackFrame()
+    //                      doWait()
+    //                          sleep()
+
+    // When LockingThread have created required stack frame it calls method doWait() and sleep(Long.MAX_VALUE)
+
+    // If LockingThread should relinquish one of the acquired monitors it should be interrupted and after
+    // interrupting should call 'wait()' for specified monitor, and for this example LockingThread will have
+    // following stack frames:
+
+    // run()
+    //  createStackFrame()
+    //      ClassWithSynchronizedMethods().synchronizedMethod() // monitor for instance of ClassWithSynchronizedMethods is acquired here
+    //          createStackFrame()
+    //              synchronizedObjectBlock()   // monitor for instance of Object is acquired here
+    //                  createStackFrame()
+    //                      doWait()
+    //                          relinquishedMonitor.wait()
+
+    // LockingThread still holds all other locks because of it didn't exit from corresponding synchronized methods and blocks.
+    // To let LockingThread acquire relinquished monitor 'relinquishedMonitor.notifyAll()' should be called, after this
+    // LockingThread will acquire this monitor again because of it still in corresponding synchronized method or block and
+    // it will have again such stack frames:
+
+    // run()
+    //  createStackFrame()
+    //      ClassWithSynchronizedMethods().synchronizedMethod() // monitor for instance of ClassWithSynchronizedMethods is acquired here
+    //          createStackFrame()
+    //              synchronizedObjectBlock()   // monitor for instance of Object is acquired here
+    //                  createStackFrame()
+    //                      doWait()
+    //                          sleep()
+    void createStackFrame() {
+        if (currentIndex < stackFramesDescription.size()) {
+            String frameDescription = stackFramesDescription.get(currentIndex);
+
+            currentIndex++;
+
+            if (frameDescription.equals(JNI_MONITOR_ENTER)) {
+                // for JNI monitors -1 is returned as stack depth
+                int currentStackDepth = -1;
+                Object object = new Object();
+                DebugMonitorInfo monitorInfo = new DebugMonitorInfo(object, currentStackDepth, this, true);
+                addMonitorInfo(monitorInfo);
+                log("Enter JNI monitor");
+                nativeJNIMonitorEnter(object);
+                log("Exit JNI monitor");
+                removeMonitorInfo(monitorInfo);
+            } else if (frameDescription.equals(SYNCHRONIZED_BLOCK_STATIC_OBJECT)) {
+                synchronizedBlockStaticObject();
+            } else if (frameDescription.equals(SYNCHRONIZED_BLOCK_STATIC_THREAD_OBJECT)) {
+                synchronizedBlockStaticThreadObject();
+            } else if (frameDescription.equals(SYNCHRONIZED_METHOD)) {
+                new ClassWithSynchronizedMethods().synchronizedMethod(this);
+            } else if (frameDescription.equals(SYNCHRONIZED_THREAD_METHOD)) {
+                synchronizedMethod();
+            } else if (frameDescription.equals(SYNCHRONIZED_STATIC_METHOD)) {
+                ClassWithSynchronizedMethods.synchronizedStaticMethod(this);
+            } else if (frameDescription.equals(SYNCHRONIZED_STATIC_THREAD_METHOD)) {
+                synchronizedStaticMethod(this);
+            } else if (frameDescription.equals(SYNCHRONIZED_THIS_BLOCK)) {
+                synchronizedThisBlock();
+            } else if (frameDescription.equals(SYNCHRONIZED_OBJECT_BLOCK)) {
+                synchronizedObjectBlock();
+            } else if (frameDescription.equals(FRAME_WITHOUT_LOCK)) {
+                frameWithoutLock();
+            } else
+                throw new TestBug("Invalid stack frame description: " + frameDescription);
+        } else {
+            // required stack is created
+            ready();
+            doWait();
+        }
+
+        if (exitSingleFrame) {
+            if (currentIndex-- < stackFramesDescription.size()) {
+                // exit from single synchronized block/method
+                ready();
+                doWait();
+            }
+        }
+    }
+
+    public Object getRelinquishedMonitor() {
+        return relinquishedMonitor;
+    }
+
+    private Object relinquishedMonitor;
+
+    private Wicket waitStateWicket = new Wicket();
+
+    private Thread.State requiredState;
+
+    public void waitState() {
+        // try wait with timeout to avoid possible hanging (if LockingThread have finished execution because of uncaught exception)
+        int result = waitStateWicket.waitFor(60000);
+
+        if (result != 0) {
+            throw new TestBug("Locking thread can't reach required state (waitStateWicket wasn't unlocked)");
+        }
+
+        if (requiredState == null)
+            throw new TestBug("Required state not specified");
+
+        long startTime = System.currentTimeMillis();
+
+        // additional check to be sure that LockingThread acquired state
+        while (this.getState() != requiredState) {
+
+            // try wait with timeout to avoid possible hanging if something will go wrong
+            if ((System.currentTimeMillis() - startTime) > 60000) {
+                throw new TestBug("Locking thread can't reach required state (state: " + requiredState + " wasn't reached) in 1 minute");
+            }
+
+            yield();
+        }
+
+        requiredState = null;
+
+        Object relinquishedMonitor = getRelinquishedMonitor();
+        /*
+         * Changing thread state and release of lock is not single/atomic operation.
+         * As result there is a potential race when thread state (LockingThread) has
+         * been changed but the lock has not been released yet. To avoid this current
+         * thread is trying to acquire the same monitor, so current thread proceeds
+         * execution only when monitor has been really relinquished by LockingThread.
+         */
+        if (relinquishedMonitor != null) {
+            synchronized (relinquishedMonitor) {
+            }
+        }
+    }
+
+    // LockingThread acquired required state
+    private void ready() {
+        waitStateWicket.unlockAll();
+    }
+
+    // is LockingThread should relinquish single monitor
+    private volatile boolean relinquishMonitor;
+
+    private int relinquishedMonitorIndex;
+
+    // relinquish single monitor with given index through Object.wait()
+    public void relinquishMonitor(int index) {
+        if (index >= monitorsInfo.size()) {
+            throw new TestBug("Invalid monitor index: " + index);
+        }
+
+        requiredState = Thread.State.WAITING;
+        waitStateWicket = new Wicket();
+        relinquishMonitor = true;
+        relinquishedMonitorIndex = index;
+
+        interrupt();
+
+        DebugMonitorInfo monitorInfo = monitorsInfo.get(relinquishedMonitorIndex);
+
+        if (monitorInfo == null)
+            throw new TestBug("Invalid monitor index: " + relinquishedMonitorIndex);
+    }
+
+    public void acquireRelinquishedMonitor() {
+        if (relinquishedMonitor == null) {
+            throw new TestBug("There is no relinquished monitor");
+        }
+
+        // Set requiredState to 'Thread.State.TIMED_WAITING' because of LockingThread call
+        // Thread.sleep(Long.MAX_VALUE) after monitor acquiring
+        requiredState = Thread.State.TIMED_WAITING;
+
+        waitStateWicket = new Wicket();
+        relinquishMonitor = false;
+
+        synchronized (relinquishedMonitor) {
+            relinquishedMonitor.notifyAll();
+        }
+    }
+
+    public void stopLockingThread() {
+        requiredState = Thread.State.TIMED_WAITING;
+
+        waitStateWicket = new Wicket();
+        exitSingleFrame = false;
+
+        interrupt();
+    }
+
+    // is thread should exit from single synchronized block/method
+    private boolean exitSingleFrame;
+
+    public void exitSingleFrame() {
+        requiredState = Thread.State.TIMED_WAITING;
+
+        waitStateWicket = new Wicket();
+        exitSingleFrame = true;
+
+        interrupt();
+    }
+
+    // LockingThread call this method when required state is reached
+    private void doWait() {
+        while (true) {
+            try {
+                Thread.sleep(Long.MAX_VALUE);
+            } catch (InterruptedException e) {
+                // expected exception, LockingThread should be interrupted to change state
+            }
+
+            // if single monitor should be relinquished through Object.wait()
+            if (relinquishMonitor) {
+                try {
+                    DebugMonitorInfo monitorInfo = monitorsInfo.get(relinquishedMonitorIndex);
+
+                    if (monitorInfo == null)
+                        throw new TestBug("Invalid monitor index: " + relinquishedMonitorIndex);
+
+                    relinquishedMonitor = monitorInfo.monitor;
+
+                    log("Relinquish monitor: " + relinquishedMonitor);
+
+                    // monitor is relinquished
+                    ready();
+
+                    // Really monitor is relinquished only when LockingThread calls relinquishedMonitor.wait(0) below,
+                    // but to be sure that LockingThread have reached required state method waitState() should be called
+                    // and this method waits when LockingThred change state to 'Thread.State.WAITING'
+
+                    while (relinquishMonitor)
+                        relinquishedMonitor.wait(0);
+
+                    log("Acquire relinquished monitor: " + relinquishedMonitor);
+                } catch (Exception e) {
+                    executedWithErrors = true;
+                    log("Unexpected exception: " + e);
+                    e.printStackTrace(log.getOutStream());
+                }
+
+                relinquishedMonitor = null;
+
+                // monitor is acquired again
+                //(becuase we still are located in the frame where lock was acquired before we relinquished it)
+                ready();
+            } else
+                // exit from frame
+                break;
+        }
+    }
+
+    public void run() {
+        // LockingThread call Thread.sleep() when required stack frame was created
+        requiredState = Thread.State.TIMED_WAITING;
+
+        createStackFrame();
+
+        // thread relinquished all monitors
+        ready();
+        doWait();
+    }
+
+    static synchronized void synchronizedStaticMethod(LockingThread lockingThread) {
+        int currentStackDepth = lockingThread.expectedDepth();
+
+        lockingThread.log("Enter synchronized static thread method");
+
+        DebugMonitorInfo monitorInfo = new DebugMonitorInfo(LockingThread.class, currentStackDepth, lockingThread, false);
+        lockingThread.addMonitorInfo(monitorInfo);
+        lockingThread.createStackFrame();
+        lockingThread.removeMonitorInfo(monitorInfo);
+
+        lockingThread.log("Exit synchronized static thread method");
+    }
+
+    // calculate stack depth at which monitor was acquired
+    int expectedDepth() {
+        // for each monitor call 2 methods: createStackFrame() and method which acquire monitor
+        // + when stack creation is finished call 3 methods: createStackFrame()->doWait()->sleep()
+        return (stackFramesDescription.size() - currentIndex) * 2 + 3;
+    }
+
+    private native void nativeJNIMonitorEnter(Object object);
+
+    synchronized void synchronizedMethod() {
+        int currentStackDepth = expectedDepth();
+
+        log("Enter synchronized thread method");
+
+        DebugMonitorInfo monitorInfo = new DebugMonitorInfo(this, currentStackDepth, this, false);
+        addMonitorInfo(monitorInfo);
+        createStackFrame();
+        removeMonitorInfo(monitorInfo);
+
+        log("Exit synchronized thread method");
+    }
+
+    void synchronizedThisBlock() {
+        int currentStackDepth = expectedDepth();
+
+        log("Enter synchronized(this) block");
+
+        synchronized (this) {
+            DebugMonitorInfo monitorInfo = new DebugMonitorInfo(this, currentStackDepth, this, false);
+            addMonitorInfo(monitorInfo);
+            createStackFrame();
+            removeMonitorInfo(monitorInfo);
+        }
+
+        log("Exit synchronized(this) block");
+    }
+
+    private static Object staticObject;
+
+    // 'staticObjectInitializingLock' is used in synchronizedBlockStaticObject() and synchronizedBlockStaticThreadObject().
+    // In this methods LockingThread initializes static object and enters in synchronized block
+    // for this static object, this actions are not thread safe(because of static fields are used) and 'staticObjectInitializingLock'
+    // is used to prevent races
+    private static ReentrantLock staticObjectInitializingLock = new ReentrantLock();
+
+    void synchronizedBlockStaticObject() {
+        int currentStackDepth = expectedDepth();
+
+        // initializing of 'staticObject' and entering to the synchronized(staticObject) block should be thread safe
+        staticObjectInitializingLock.lock();
+
+        staticObject = new Object();
+
+        log("Enter synchronized(static object) block");
+
+        synchronized (staticObject) {
+            // thread unsafe actions was done
+            staticObjectInitializingLock.unlock();
+
+            DebugMonitorInfo monitorInfo = new DebugMonitorInfo(staticObject, currentStackDepth, this, false);
+            addMonitorInfo(monitorInfo);
+            createStackFrame();
+            removeMonitorInfo(monitorInfo);
+        }
+
+        log("Exit synchronized(static object) block");
+    }
+
+    private static LockingThread staticLockingThread;
+
+    void synchronizedBlockStaticThreadObject() {
+        int currentStackDepth = expectedDepth();
+
+        // initializing of 'staticLockingThread' and entering to the synchronized(staticLockingThread) block should be thread safe
+        staticObjectInitializingLock.lock();
+
+        staticLockingThread = this;
+
+        log("Enter synchronized(static thread object) block");
+
+        synchronized (staticLockingThread) {
+            // thread unsafe actions was done
+            staticObjectInitializingLock.unlock();
+
+            DebugMonitorInfo monitorInfo = new DebugMonitorInfo(staticLockingThread, currentStackDepth, this, false);
+            addMonitorInfo(monitorInfo);
+            createStackFrame();
+            removeMonitorInfo(monitorInfo);
+        }
+
+        log("Exit synchronized(static thread object) block");
+    }
+
+    void synchronizedObjectBlock() {
+        int currentStackDepth = expectedDepth();
+
+        Object object = new Object();
+
+        log("Enter synchronized(object) block");
+
+        synchronized (object) {
+            DebugMonitorInfo monitorInfo = new DebugMonitorInfo(object, currentStackDepth, this, false);
+            addMonitorInfo(monitorInfo);
+            createStackFrame();
+            removeMonitorInfo(monitorInfo);
+        }
+
+        log("Exit synchronized(object) block");
+    }
+
+    private void frameWithoutLock() {
+        log("Enter frameWithoutLock");
+
+        createStackFrame();
+
+        for (DebugMonitorInfo monitor : monitorsInfo)
+            monitor.stackDepth -= 2;
+
+        log("Exit frameWithoutLock");
+    }
+}
+
+//class containing synchronized method and synchronized static method, used by LockingThread
+class ClassWithSynchronizedMethods {
+    public synchronized void synchronizedMethod(LockingThread lockingThread) {
+        int currentStackDepth = lockingThread.expectedDepth();
+
+        lockingThread.log("Enter synchronized method");
+
+        LockingThread.DebugMonitorInfo monitorInfo = new LockingThread.DebugMonitorInfo(this, currentStackDepth, lockingThread, false);
+        lockingThread.addMonitorInfo(monitorInfo);
+        lockingThread.createStackFrame();
+        lockingThread.removeMonitorInfo(monitorInfo);
+
+        lockingThread.log("Exit synchronized method");
+    }
+
+    public static synchronized void synchronizedStaticMethod(LockingThread lockingThread) {
+        int currentStackDepth = lockingThread.expectedDepth();
+
+        lockingThread.log("Enter synchronized static method");
+
+        LockingThread.DebugMonitorInfo monitorInfo = new LockingThread.DebugMonitorInfo(ClassWithSynchronizedMethods.class, currentStackDepth,
+                lockingThread, false);
+        lockingThread.addMonitorInfo(monitorInfo);
+        lockingThread.createStackFrame();
+        lockingThread.removeMonitorInfo(monitorInfo);
+
+        lockingThread.log("Exit synchronized static method");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/MonitorLockingThread.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+/*
+ *  Thread intended to hold given lock until method releaseLock() not called
+ *
+ *   Example of usage:
+ *
+ *   Object lockToHold = new Object();
+ *   MonitorLockingThread lockingThread = new MonitorLockingThread(lockToHold);
+ *
+ *   // after calling this method lock 'lockToHold' is acquired by lockingThread
+ *   lockingThread.acquireLock();
+ *
+ *   // after calling this method lockingThread releases 'lockToHold' and finishes execution
+ *   lockingThread.releaseLock();
+ */
+public class MonitorLockingThread extends Thread {
+    /*
+     *   Class MonitorLockingThread is written for usage in tests provoking monitor contention.
+     *   Typically in these tests exists thread holding lock (MonitorLockingThread) and another
+     *   thread trying to acquire the same lock. But this scenario also requires one more thread
+     *   which will force MonitorLockingThread to release lock when contention occurred, for this purpose
+     *   auxiliary thread class LockFreeThread is written.
+     *
+     *   Example of usage of MonitorLockingThread and LockFreeThread:
+     *
+     *   Object lock = new Object();
+     *   MonitorLockingThread monitorLockingThread = new MonitorLockingThread(lock);
+     *
+     *   MonitorLockingThread.LockFreeThread lockFreeThread =
+     *       new MonitorLockingThread.LockFreeThread(Thread.currentThread(), monitorLockingThread);
+     *
+     *   monitorLockingThread.acquireLock();
+     *
+     *   lockFreeThread.start();
+     *
+     *   // try to acquire lock which is already held by MonitorLockingThread (here monitor contention should occur),
+     *   // when LockFreeThread finds that contention occurred it forces MonitorLockingThread to release lock
+     *   // and current thread is able to continue execution
+     *   synchronized (lock) {
+     *   }
+     */
+    public static class LockFreeThread extends Thread {
+        private Thread blockedThread;
+
+        private MonitorLockingThread lockingThread;
+
+        public LockFreeThread(Thread blockedThread, MonitorLockingThread lockingThread) {
+            this.blockedThread = blockedThread;
+            this.lockingThread = lockingThread;
+        }
+
+        public void run() {
+            /*
+             * Wait when blockedThread's state will switch to 'BLOCKED' (at that moment monitor contention
+             * should already occur) and then force MonitorLockingThread to release lock
+             */
+            while (blockedThread.getState() != Thread.State.BLOCKED)
+                yield();
+
+            lockingThread.releaseLock();
+        }
+    }
+
+    private volatile boolean isRunning = true;
+
+    private volatile boolean holdsLock;
+
+    private Object lockToHold;
+
+    public MonitorLockingThread(Object lockToHold) {
+        this.lockToHold = lockToHold;
+    }
+
+    public void run() {
+        synchronized (lockToHold) {
+            holdsLock = true;
+            while (isRunning)
+                yield();
+        }
+        holdsLock = false;
+    }
+
+    public void releaseLock() {
+        isRunning = false;
+        while (holdsLock)
+            yield();
+    }
+
+    public void acquireLock() {
+        start();
+        while (!holdsLock)
+            yield();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/ReentrantLockLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import java.util.concurrent.locks.ReentrantLock;
+import nsk.share.Wicket;
+
+/*
+ *  Class used for deadlock creation, acquires java.util.concurrent.locks.ReentrantLock
+ */
+public class ReentrantLockLocker extends DeadlockLocker {
+    private ReentrantLock lock = new ReentrantLock();
+
+    public ReentrantLockLocker(Wicket step1, Wicket step2, Wicket readyWicket) {
+        super(step1, step2, readyWicket);
+    }
+
+    public ReentrantLock getLock() {
+        return lock;
+    }
+
+    protected void doLock() {
+        lock.lock();
+
+        try {
+            step1.unlockAll();
+            step2.waitFor();
+            readyWicket.unlock();
+            inner.lock();
+        } finally {
+            lock.unlock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/SynchronizedBlockLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import nsk.share.Wicket;
+
+/*
+ *  Class used for deadlock creation, acquires java lock
+ *  using synchronized block
+ */
+public class SynchronizedBlockLocker extends DeadlockLocker {
+    private Object object = new Object();
+
+    public SynchronizedBlockLocker(Wicket step1, Wicket step2, Wicket readyWicket) {
+        super(step1, step2, readyWicket);
+    }
+
+    public Object getLock() {
+        return object;
+    }
+
+    protected void doLock() {
+        synchronized (object) {
+            step1.unlockAll();
+            step2.waitFor();
+            readyWicket.unlock();
+            inner.lock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/locks/SynchronizedMethodLocker.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.locks;
+
+import nsk.share.Wicket;
+
+/*
+ *  Class used for deadlock creation, acquires java lock
+ *  using synchronized method
+ */
+public class SynchronizedMethodLocker extends DeadlockLocker {
+    public SynchronizedMethodLocker(Wicket step1, Wicket step2, Wicket readyWicket) {
+        super(step1, step2, readyWicket);
+    }
+
+    public Object getLock() {
+        return this;
+    }
+
+    protected synchronized void doLock() {
+        step1.unlock();
+        step2.waitFor();
+        readyWicket.unlock();
+        inner.lock();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/log/Log.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.log;
+
+/**
+ * Log interface.
+ */
+public interface Log {
+        /**
+         * Log at INFO level.
+         *
+         * @param o object to log
+         */
+        public void info(Object o);
+
+        /**
+         * Log at DEBUG level.
+         *
+         * @param o object to log
+         */
+        public void debug(Object o);
+
+        /**
+         * Log at WARN level.
+         *
+         * @param o object to log
+         */
+        public void warn(Object o);
+
+        /**
+         * Log at ERROR level
+         *
+         * @param o object to log
+         */
+        public void error(Object o);
+
+        /**
+         * Determine if logging at DEBUG level.
+         *
+         * @return true if debug logging is enabled, false otherwise
+         */
+        public boolean isDebugEnabled();
+
+        /**
+         * Determine if logging at INFO level.
+         *
+         * @return true if info logging is enabled, false otherwise
+         */
+        public boolean isInfoEnabled();
+
+        /**
+         * Determine if logging at WARN level.
+         *
+         * @return true if warn logging is enabled, false otherwise
+         */
+        public boolean isWarnEnabled();
+
+        /**
+         * Determine if logging at ERROR level.
+         *
+         * @return true if error logging is enabled, false otherwise
+         */
+        public boolean isErrorEnabled();
+
+        /**
+         * Enable/disable info output.
+         *
+         * @param infoEnabled
+         */
+        public void setInfoEnabled(boolean infoEnabled);
+
+        /**
+         * Enable/disable debug output.
+         *
+         * @param debugEnabled
+         */
+        public void setDebugEnabled(boolean debugEnabled);
+
+        /**
+         * Enable/disable warn output.
+         * @param warnEnabled
+         */
+        public void setWarnEnabled(boolean warnEnabled);
+
+        /**
+         * Enable/disable error output.
+         * @param errorEnabled
+         */
+        public void setErrorEnabled(boolean errorEnabled);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/log/LogAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.log;
+
+/**
+ * Marker interface to inject Log.
+ * @see nsk.share.log.Log
+ */
+public interface LogAware {
+        /**
+         * Set log to use.
+         *
+         * @param log log
+         */
+        public void setLog(Log log);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/log/LogSupport.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.log;
+
+import java.io.PrintStream;
+
+/**
+ * Basic Log that outputs to PrintStream.
+ *
+ * This log also tries to catch OutOfMemoryErrors and retry.
+ *
+ * @see nsk.share.log.Log
+ */
+public class LogSupport implements Log {
+        private final int attempts = 2;
+        private PrintStream out;
+        private boolean infoEnabled = true;
+        private boolean debugEnabled = true;
+        private boolean warnEnabled = true;
+        private boolean errorEnabled = true;
+
+        public LogSupport() {
+                this(System.out);
+        }
+
+        public LogSupport(PrintStream out) {
+                this.out = out;
+        }
+
+        protected void logObject(Object o) {
+                if (o instanceof Throwable) {
+                        logThrowable((Throwable) o);
+                        return;
+                }
+                for (int i = 0; i < attempts; ++i) {
+                        try {
+                                out.println(o.toString());
+                                out.flush();
+                                break;
+                        } catch (OutOfMemoryError e) {
+                                System.gc();
+                                try {
+                                        Thread.sleep(500);
+                                } catch (InterruptedException ie) {
+                                }
+                        }
+                }
+                out.flush();
+        }
+
+        protected void logThrowable(Throwable o) {
+                for (int i = 0; i < attempts; ++i) {
+                        try {
+                                o.printStackTrace(out);
+                                out.flush();
+                                break;
+                        } catch (OutOfMemoryError e) {
+                                System.gc();
+                                try {
+                                        Thread.sleep(500);
+                                } catch (InterruptedException ie) {
+                                }
+                        }
+                }
+                out.flush();
+        }
+
+        public void info(Object o) {
+                if (infoEnabled)
+                        logObject(o);
+        }
+
+        public void debug(Object o) {
+                if (debugEnabled)
+                        logObject(o);
+        }
+
+        public void warn(Object o) {
+                if (warnEnabled)
+                        logObject(o);
+        }
+
+        public void error(Object o) {
+                if (errorEnabled)
+                        logObject(o);
+        }
+
+        public boolean isInfoEnabled() {
+                return infoEnabled;
+        }
+
+        public void setInfoEnabled(boolean infoEnabled) {
+                this.infoEnabled = infoEnabled;
+        }
+
+        public boolean isDebugEnabled() {
+                return debugEnabled;
+        }
+
+        public void setDebugEnabled(boolean debugEnabled) {
+                this.debugEnabled = debugEnabled;
+        }
+
+        public boolean isWarnEnabled() {
+                return warnEnabled;
+        }
+
+        public void setWarnEnabled(boolean warnEnabled) {
+                this.warnEnabled = warnEnabled;
+        }
+
+        public boolean isErrorEnabled() {
+                return errorEnabled;
+        }
+
+        public void setErrorEnabled(boolean errorEnabled) {
+                this.errorEnabled = errorEnabled;
+        }
+
+        public void setOut(PrintStream out) {
+                this.out = out;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/README	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,186 @@
+Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+This code is free software; you can redistribute it and\\\/or modify it
+under the terms of the GNU General Public License version 2 only, as
+published by the Free Software Foundation.
+This code is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+version 2 for more details (a copy is included in the LICENSE file that
+accompanied this code).
+
+You should have received a copy of the GNU General Public License version
+2 along with this work; if not, write to the Free Software Foundation,
+Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+or visit www.oracle.com if you need additional information or have any
+questions.
+
+---------------------------------------------------------------------------------
+
+This directory contains source files of testbase_nsk native
+framework, which provides support for native tests.
+
+    Source files:
+        nsk_tools.h
+        nsk_tools.c
+
+    Naming conventions:
+        macroses:  NSK_*
+        functions: nsk_*
+
+Also this directory provides support for running native threads
+in a platform independent manner.
+
+    Source files:
+        native_thread.h
+        native_thread.c
+
+    Naming conventions:
+        functions: THREAD_*
+
+The following source files declares a set of functions which
+provides support for lists of various objects
+
+    Source files:
+        nsk_list.h
+        nsk_list.c
+
+    Naming conventions:
+        functions: nsk_list_*
+
+---------------------------------------------------------------------------------
+
+nsk_tools.h
+
+Provides functions and macroses for the most usefull actions:
+
+    - access native JVM environment in a compiler independent manner
+
+        NSK_CPP_STUBn(function, env, arg1, ..., argn)
+
+    - print error message with arguments
+
+        NSK_COMPLAINn(format, arg1, ..., argn)
+
+    - print verbose message with arguments
+
+        NSK_DISPLAYn(format, arg1, ..., argn)
+
+    - trace action execution
+
+        NSK_TRACE(action)
+
+    - trace action, check result for true/false and print error if required
+
+        NSK_VERIFY(action)
+        NSK_VERIFY_NEGATIVE(action)
+
+    - set verbose and trace mode of test output
+
+        void nsk_setVerboseMode(int verbose);
+        int  nsk_getVerboseMode();
+
+        void nsk_setTraceMode(int mode);
+        int  nsk_getTraceMode();
+
+    - miscelaneous functions for printing messages
+      (hidden by above mentioned macroses)
+
+Typical example of using macroses NSK_CPP_STUB and NSK_VERIFY
+for accesing JVM native environment:
+
+    // jvm->GetEnv(jvm, &env, version)
+    if (!NSK_VERIFY(
+            NSK_CPP_STUB3(GetEnv, jvm, &env, JNI_VERSION_1_2) == JNI_OK)) {
+        return JNI_ERR;
+    }
+
+For more specific checks in invocations of JNI and JVMTI functions
+use special macroses defined in share/jni and share/jvmti frameworks.
+
+---------------------------------------------------------------------------------
+
+native_thread.h
+
+Provides platform-independent support for running native threads:
+
+    - manage native threads
+
+    void* THREAD_new(PROCEDURE procedure, void* context);
+    void* THREAD_start(void* thread);
+    void  THREAD_waitFor(void* thread);
+    void  THREAD_sleep(int seconds);
+
+    - get status of native threads
+
+    int THREAD_isStarted(void* thread);
+    int THREAD_hasFinished(void* thread);
+    int THREAD_status(void* thread);
+
+---------------------------------------------------------------------------------
+
+nsk_list.h
+
+Provides support for lists of various objects:
+
+    - managing list
+    const void* nsk_list_Create();
+    int         nsk_list_Destroy(const void *plist);
+
+    - managing elements
+    const void* nsk_list_Add(const void *plist, const void *p);
+    int         nsk_list_Delete(const void *plist, int ind);
+
+    - getting element info
+    int         nsk_list_getCount(const void *plist);
+    const void* nsk_list_Get(const void *plist, int ind);
+
+Typical example:
+
+int TOTAL_COUNT = 10;
+typedef struct recordStruct {
+    int field1;
+    int field2;
+} record;
+
+main() {
+    int i;
+    record *rec;
+    const void *plist;
+
+    /* creating list */
+    plist = nsk_list_create();
+
+    /* adding new elements */
+    for (i = 0; i < TOTAL_COUNT; i ++) {
+        rec = (record *)malloc(sizeof(record));
+        rec->field1 = i;
+        rec->field2 = i * 10;
+        if (!nsk_list_add(plist, rec)) {
+            free((void *)rec);
+        }
+    }
+
+    /* getting elements */
+    for (i = 0; i < TOTAL_COUNT; i ++) {
+        rec = (record *)nsk_list_get(plist, i);
+        printf("%3d %3d\n", rec->field1, rec->field2);
+    }
+
+    /* deleteing elements */
+    for (i = 0; i < TOTAL_COUNT; i ++) {
+        rec = (record *)nsk_list_get(plist, i);
+        free(rec);
+        nsk_list_remove(plist, 0);
+    }
+
+    /* destroying list */
+    nsk_list_destroy(plist);
+
+}
+
+---------------------------------------------------------------------------------
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,211 @@
+/*
+* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* testbase_nsk threads: */
+#include <native_thread.h>
+
+/***************************************************************/
+
+#ifdef _WIN32
+
+#define windows
+#include <windows.h>
+#include <process.h> /* for thread routines */
+typedef  unsigned int  THREAD_ID;
+
+#else // !_WIN32
+
+#include <unistd.h>
+
+#ifdef sun
+#include <thread.h>
+typedef  thread_t  THREAD_ID;
+#else // !sun
+#include <pthread.h>
+typedef  pthread_t  THREAD_ID;
+#endif // !sun
+
+#endif // !_WIN32
+
+/***************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A mirror to control a thread.
+ */
+typedef
+    struct STRUCT_THREAD {
+        PROCEDURE procedure;
+        void* context;
+        /**/
+        int started;
+        int finished;
+        int status;
+        /**/
+        THREAD_ID id;
+    }
+    THREAD;
+
+/***************************************************************/
+
+/**
+ * Return a new thread mirror, or NULL if failed.
+ */
+void* THREAD_new(PROCEDURE procedure, void* context) {
+    THREAD* thread = (THREAD*)malloc(sizeof(THREAD));
+    if (thread == NULL)
+        return NULL;
+    thread->procedure = procedure;
+    thread->context   = context;
+    thread->started   = 0; /* No */
+    thread->finished  = 0;
+    thread->status   = -1; /* undefined */
+    return thread;
+}
+
+/***************************************************************/
+
+#ifdef windows
+unsigned __stdcall procedure(void* t) {
+#else // !windows
+void* procedure(void* t) {
+#endif
+    THREAD* thread = (THREAD*)t;
+    thread->started  = 1;
+    thread->status   = thread->procedure(thread->context);
+    thread->finished = 1;
+    return 0;
+}
+
+/**
+ * Return the thread if started OK, or NULL if failed.
+ */
+void* THREAD_start(void* t) {
+    THREAD* thread = (THREAD*)t;
+    if (thread == NULL)
+        return NULL;
+    if (thread->started != 0)
+        return NULL;
+/*  thread->started  = 0;      -- not yet */
+    thread->finished = 0;
+    thread->status   = 0;
+    {
+
+#ifdef windows
+    uintptr_t result = _beginthreadex(NULL,0,procedure,thread,0,&(thread->id));
+    if (result == 0) {
+        perror("failed to create a native thread");
+        return NULL;
+    }
+#elif sun
+    int result = thr_create(NULL,0,procedure,thread,0,&(thread->id));
+    if (result != 0) {
+        perror("failed to create a native thread");
+        return NULL;
+    }
+#else // !windows & !sun
+    int result = pthread_create(&(thread->id),NULL,procedure,thread);
+    if (result != 0) {
+        perror("failed to create a native thread");
+        return NULL;
+    }
+#endif // !windows & !sun
+    };
+    return thread;
+}
+
+/***************************************************************/
+
+/**
+ * Return 1 if the thread has been started, or 0 if not,
+ * or -1 if thread==NULL.
+ */
+int THREAD_isStarted(void* t) {
+    THREAD* thread = (THREAD*)t;
+    if (thread == NULL)
+        return -1;
+    return (thread->started == 1);
+}
+
+/**
+ * Return 1 if the thread has been started and already has finished,
+ * or 0 if the thread hasn't finish (or even hasn't been started),
+ * or -1 if thread==NULL.
+ */
+int THREAD_hasFinished(void* t) {
+    THREAD* thread = (THREAD*)t;
+    if (thread == NULL)
+        return -1;
+    return (thread->finished == 1);
+}
+
+/**
+ * Return thread->status if thread has finished,
+ * or return 0 if thread hasn't finished,
+ * or retuen -1 if thread==NULL.
+ */
+int THREAD_status(void* t) {
+    THREAD* thread = (THREAD*)t;
+    if (thread == NULL)
+        return -1;
+    return thread->status;
+}
+
+/***************************************************************/
+
+/**
+ * Cycle with 1 second sleeps until the thread has finished;
+ * or return immediately, if thread==NULL.
+ */
+void THREAD_waitFor(void* t) {
+    THREAD* thread = (THREAD*)t;
+    if (thread == NULL)
+        return;
+    while (thread->finished == 0)
+        THREAD_sleep(1); /* yield for a second */
+}
+
+/***************************************************************/
+
+/**
+ * Current thread sleeps.
+ */
+void THREAD_sleep(int seconds) {
+#ifdef windows
+    Sleep(1000L * seconds);
+#else
+    sleep(seconds);
+#endif
+}
+
+/***************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_thread.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NSK_SHARE_NATIVE_NATIVE_THREAD_H
+#define NSK_SHARE_NATIVE_NATIVE_THREAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A thread procedure with a void* argument and returning
+ * a status.
+ */
+typedef int(*PROCEDURE)(void*);
+
+/**
+ * Return a thread mirror, or NULL if failed.
+ */
+void* THREAD_new(PROCEDURE procedure, void* context);
+
+/**
+ * Return the thread if started OK, or NULL if failed.
+ */
+void* THREAD_start(void* thread);
+
+/**
+ * Return 1 if the thread has been started, or 0 if not,
+ * or -1 if thread==NULL.
+ */
+int THREAD_isStarted(void* thread);
+
+/**
+ * Return 1 if the thread has been started and already has finished,
+ * or 0 if the thread hasn't finish (or even hasn't been started),
+ * or -1 if thread==NULL.
+ */
+int THREAD_hasFinished(void* thread);
+
+/**
+ * Return thread->status if thread has finished,
+ * or return 0 if thread hasn't finished,
+ * or retuen -1 if thread==NULL.
+ */
+int THREAD_status(void* thread);
+
+/**
+ * Cycle with 1 second sleeps until the thread has finished;
+ * or return immediately, if thread==NULL.
+ */
+void THREAD_waitFor(void* thread);
+
+/**
+ * Current thread sleeps.
+ */
+void THREAD_sleep(int seconds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_utils.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <stdio.h>
+
+#if (defined(WIN32) || defined (_WIN32) )
+#include <process.h>
+#define getpid _getpid
+#define pidType int
+#else
+#include <unistd.h>
+#define pidType pid_t
+#endif
+
+#include <sys/types.h>
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jlong
+JNICALL Java_nsk_share_NativeUtils_getCurrentPID(JNIEnv * jni, jobject  jobj) {
+        return (jlong) getpid();
+}
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nsk_list.h"
+#include "nsk_tools.h"
+
+#define NSK_LIST_INIT_COUNT 20
+
+typedef struct nsk_list_infoStruct {
+    const void **arr;
+    int elements_count;
+    int allocated_count;
+} nsk_list_info;
+
+
+static int nsk_list_size_void = sizeof(void *);
+
+/* ============================================================================= */
+
+const void* nsk_list_create() {
+
+    nsk_list_info *list_info;
+
+    /* create nsk_list_info */
+    list_info = (nsk_list_info *)malloc(sizeof(nsk_list_info));
+    if (list_info == NULL) {
+        return NULL;
+    }
+
+    list_info->allocated_count = NSK_LIST_INIT_COUNT;
+    list_info->elements_count = 0;
+    list_info->arr = (const void **)malloc(list_info->allocated_count * nsk_list_size_void);
+    if (list_info->arr == NULL) {
+        free(list_info);
+        return NULL;
+    }
+
+    return list_info;
+}
+
+/* ============================================================================= */
+
+int nsk_list_destroy(const void *plist) {
+
+    const nsk_list_info *list_info = (const nsk_list_info *)plist;
+
+    free((void *)list_info->arr);
+    free((void *)plist);
+
+    return NSK_TRUE;
+}
+
+/* ============================================================================= */
+
+int nsk_list_add(const void *plist, const void *p) {
+
+    nsk_list_info *list_info = (nsk_list_info *)plist;
+
+    if (list_info->elements_count >= list_info->allocated_count) {
+        list_info->allocated_count += NSK_LIST_INIT_COUNT;
+        list_info->arr = (const void **)realloc((void *)list_info->arr, list_info->allocated_count * nsk_list_size_void);
+        if (list_info->arr == NULL) {
+            return NSK_FALSE;
+        }
+    }
+    list_info->arr[list_info->elements_count++] = p;
+
+    return NSK_TRUE;
+}
+
+/* ============================================================================= */
+
+int nsk_list_remove(const void *plist, int ind) {
+
+    nsk_list_info *list_info = (nsk_list_info *)plist;
+
+    if ((list_info->elements_count <= 0)
+            || ((ind < 0) || (ind >= list_info->elements_count)))
+        return NSK_FALSE;
+
+    {
+        int i;
+        for (i = ind+1; i < list_info->elements_count; i++) {
+            list_info->arr[i - 1] = list_info->arr[i];
+        }
+    }
+    list_info->arr[--list_info->elements_count] = 0;
+
+    return NSK_TRUE;
+}
+
+/* ============================================================================= */
+
+int nsk_list_getCount(const void *plist) {
+
+    return ((const nsk_list_info *)plist)->elements_count;
+}
+
+/* ============================================================================= */
+
+const void* nsk_list_get(const void *plist, int i) {
+
+    const nsk_list_info *list_info = (const nsk_list_info *)plist;
+
+    if ((i >= 0) && (i < list_info->elements_count)) {
+        return list_info->arr[i];
+    }
+
+    return NULL;
+}
+
+/* ============================================================================= */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_list.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NSK_LIST
+#define NSK_LIST
+
+/**
+ * Prepares array of pointers which has fixed INITIAL_SIZE.
+ * Memory for this array will be reallocated at the nsk_list_add()
+ * invocation if it is required.
+ *
+ * To release memory call nsk_list_destroy()
+ *
+ */
+const void* nsk_list_create();
+
+/**
+ * Releases memory allocated for array of pointer
+ * Returns NSK_TRUE if array was successfully released
+ */
+int nsk_list_destroy(const void *plist);
+
+/**
+ * Returns number of elements
+ */
+int nsk_list_getCount(const void *plist);
+
+/**
+ * Returns pointer to i-th element.
+ * User must care for type cast of this pointer
+ */
+const void* nsk_list_get(const void *plist, int i);
+
+/**
+ * Adds new element into array.
+ * If array is full then memory is reallocated so as
+ * array could contain additional INITIAL_SIZE elements
+ * Returns NSK_TRUE if pointer was successfully added
+ */
+int nsk_list_add(const void *plist, const void *p);
+
+/**
+ * Removes i-th pointer from array
+ */
+int nsk_list_remove(const void *plist, int i);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_mutex.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include "nsk_mutex.h"
+
+#ifndef _WIN32
+
+#include <pthread.h>
+
+MUTEX* MUTEX_create()
+{
+        MUTEX* mutex = (MUTEX*)malloc(sizeof(pthread_mutex_t));
+        if (mutex)
+        {
+                pthread_mutex_init((pthread_mutex_t*)mutex, NULL);
+        }
+        return mutex;
+}
+
+void MUTEX_acquire(MUTEX* mutex)
+{
+        pthread_mutex_lock((pthread_mutex_t*)mutex);
+}
+
+void MUTEX_release(MUTEX* mutex)
+{
+        pthread_mutex_unlock((pthread_mutex_t*)mutex);
+}
+
+void MUTEX_destroy(MUTEX* mutex)
+{
+        pthread_mutex_destroy((pthread_mutex_t*)mutex);
+
+        free(mutex);
+}
+
+#else // _WIN32
+
+#include <windows.h>
+
+MUTEX* MUTEX_create()
+{
+        MUTEX* mutex = (MUTEX*)malloc(sizeof(CRITICAL_SECTION));
+        if (mutex)
+        {
+                InitializeCriticalSection((PCRITICAL_SECTION)mutex);
+        }
+        return mutex;
+}
+
+void MUTEX_acquire(MUTEX* mutex)
+{
+        EnterCriticalSection((PCRITICAL_SECTION)mutex);
+}
+
+void MUTEX_release(MUTEX* mutex)
+{
+        LeaveCriticalSection((PCRITICAL_SECTION)mutex);
+}
+
+void MUTEX_destroy(MUTEX* mutex)
+{
+        DeleteCriticalSection((PCRITICAL_SECTION)mutex);
+
+        free(mutex);
+}
+
+#endif // _WIN32
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_mutex.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NSK_MUTEX_H
+#define NSK_MUTEX_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Structure to hold mutex data (the content is platform-specific)
+ */
+typedef struct _MUTEX MUTEX;
+
+/**
+ * Create a mutex
+ */
+MUTEX* MUTEX_create();
+
+/**
+ * Acquire a mutex
+ */
+void MUTEX_acquire(MUTEX* mutex);
+
+/**
+ * Release a mutex
+ */
+void MUTEX_release(MUTEX* mutex);
+
+/**
+ * Destroy a mutex
+ */
+void MUTEX_destroy(MUTEX* mutex);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+
+/*************************************************************/
+
+#include "nsk_tools.h"
+
+/*************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*************************************************************/
+
+static struct {
+    int verbose;
+    int tracing;
+    int nComplains;
+} nsk_context = {NSK_FALSE, NSK_TRACE_NONE, 0};
+
+void nsk_setVerboseMode(int verbose) {
+    nsk_context.verbose = verbose;
+}
+
+int  nsk_getVerboseMode() {
+    return nsk_context.verbose;
+}
+
+void nsk_setTraceMode(int mode) {
+    nsk_context.tracing = mode;
+}
+
+int  nsk_getTraceMode() {
+    return nsk_context.tracing;
+}
+
+/*************************************************************/
+
+static const char* file_basename(const char* fullname) {
+    const char* p;
+    const char* base = fullname;;
+
+    if (fullname == NULL)
+        return NULL;
+
+    for (p = fullname; *p != '\0'; p++) {
+        if (*p == '/' || *p == '\\')
+            base = p + 1;
+    }
+    return base;
+}
+
+/*************************************************************/
+
+void nsk_display(const char format[], ...) {
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvdisplay(NULL,0,format,ap);
+    va_end(ap);
+}
+
+void nsk_ldisplay(const char file[], int line, const char format[], ...) {
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvdisplay(file,line,format,ap);
+    va_end(ap);
+}
+
+void nsk_vdisplay(const char format[], va_list ap) {
+    nsk_lvdisplay(NULL,0,format,ap);
+}
+
+void nsk_lvdisplay(const char file[], int line, const char format[], va_list ap)
+{
+    if (!nsk_context.verbose)
+        return;
+    if (file != NULL)
+        (void) nsk_printf("- %s, %d: ",file_basename(file),line);
+    (void) nsk_vprintf(format,ap);
+}
+
+/*************************************************************/
+
+void nsk_complain(const char format[], ...) {
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvcomplain(NULL,0,format,ap);
+    va_end(ap);
+}
+
+void nsk_lcomplain(const char file[], int line, const char format[], ...)
+{
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvcomplain(file,line,format,ap);
+    va_end(ap);
+}
+
+void nsk_vcomplain(const char format[], va_list ap) {
+    nsk_lvcomplain(NULL,0,format,ap);
+}
+
+void nsk_lvcomplain(const char file[], int line,
+    const char format[], va_list ap)
+{
+    char msg_buf[1024];
+    nsk_context.nComplains++;
+    if (!nsk_context.verbose) {
+        if ( nsk_context.nComplains > NSK_MAX_COMPLAINS_NON_VERBOSE ) {
+            return;
+        }
+
+        if ( nsk_context.nComplains == NSK_MAX_COMPLAINS_NON_VERBOSE ) {
+            nsk_printf("# ...\n"
+                       "# ERROR: too many complains, giving up to save disk space (CR 6341460)\n"
+                       "# Please rerun the test with -verbose option to listen to the entire song\n");
+            return;
+        }
+    }
+
+    // Generate the message into a temp buffer since we can't call vfprintf on it twice,
+    // and also may need to modify a copy of the message slightly.
+    (void) vsnprintf(msg_buf, sizeof(msg_buf), format, ap);
+
+    // Print a fake exception with the error for failure analysis.
+    // Do this only for the first complaint.
+    if (nsk_context.nComplains == 1) {
+      char msg_buf2[sizeof(msg_buf)];
+      char* nl_ptr;
+      strncpy(msg_buf2, msg_buf, sizeof(msg_buf2));
+      // Only include up to the 1st newline in the exception's error message.
+      nl_ptr = strchr(msg_buf2, '\n');
+      if (nl_ptr != NULL) {
+        nl_ptr++;       // Skip past the newline char.
+        *nl_ptr = '\0'; // Terminate the string after the newline char.
+      } else if (strlen(msg_buf2) != 0) {
+        msg_buf2[strlen(msg_buf2)-1] = '\n'; // Make sure we have a newline char at the end.
+      }
+      (void) nsk_printf("The following fake exception stacktrace is for failuire analysis. \n");
+      (void) nsk_printf("nsk.share.Fake_Exception_for_RULE_Creation: ");
+      if (file != NULL) {
+        (void) nsk_printf("(%s:%d) ", file_basename(file), line);
+      }
+      (void) nsk_printf(msg_buf2);
+      (void) nsk_printf("\tat nsk_lvcomplain(%s:%d)\n", file_basename(__FILE__), __LINE__);
+    }
+
+    if (file != NULL) {
+        (void) nsk_printf("# ERROR: %s, %d: ", file_basename(file), line);
+    } else {
+        (void) nsk_printf("# ERROR: ");
+    }
+    (void) nsk_printf(msg_buf);
+}
+
+/*************************************************************/
+
+void nsk_ltrace(int mode, const char file[], int line, const char format[], ...) {
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvtrace(mode,file,line,format,ap);
+    va_end(ap);
+}
+
+void nsk_lvtrace(int mode, const char file[], int line, const char format[], va_list ap)
+{
+    if ((nsk_context.tracing & mode) == 0) {
+        return;
+    }
+
+    {
+        const char* prefix;
+        switch (mode) {
+            case NSK_TRACE_BEFORE:
+                prefix = ">>";
+                break;
+            case NSK_TRACE_AFTER:
+                prefix = "<<";
+                break;
+            default:
+                prefix = "..";
+                break;
+        }
+
+        (void) nsk_printf("- %s, %d: %s ",file_basename(file),line,prefix);
+        (void) nsk_vprintf(format,ap);
+    }
+}
+
+/*************************************************************/
+
+int nsk_lverify(int value, const char file[], int line, const char format[], ...)
+{
+    int fail=0;
+    va_list ap;
+    va_start(ap,format);
+    nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap);
+    if (!value) {
+        nsk_lvcomplain(file,line,format,ap);
+        nsk_printf("#   verified assertion is FALSE\n");
+        fail=1;
+    };
+    va_end(ap);
+    return !fail;
+}
+
+/*************************************************************/
+
+int nsk_vprintf(const char format[], va_list ap) {
+    int x = vfprintf(stdout,format,ap);
+    int err = fflush(stdout);
+    if (err != 0) {
+      printf("stdout: fflush failed - err=%d errno=%d x=%d\n", err, errno, x);
+      fprintf(stderr, "stderr: fflush failed - err=%d errno=%d x=%d\n", err, errno, x);
+    }
+    assert(err == 0);
+    return x;
+}
+
+int nsk_printf(const char format[], ...) {
+    int x;
+    va_list ap;
+    va_start(ap,format);
+    x = nsk_vprintf(format,ap);
+    va_end(ap);
+    return x;
+}
+
+/*************************************************************/
+
+#define MAX_HEX_COLUMNS  255
+
+void nsk_printHexBytes(const char indent[], int columns,
+                                    size_t size, const unsigned char bytes[]) {
+    char hex[MAX_HEX_COLUMNS * 3 + 1];
+    char ascii[MAX_HEX_COLUMNS + 1];
+    char buf[16];
+
+    size_t i;
+
+    if (size <= 0 || bytes == NULL)
+        return;
+
+    for (i = 0; i < size; i += columns) {
+        int j;
+
+        hex[0] = '\0';
+        ascii[0] = '\0';
+
+        for (j = 0; j < columns && (i + j) < size; j++) {
+            unsigned int b = (unsigned int)bytes[i + j] & 0xFF;
+            char ch = (char)bytes[i + j];
+
+            if (!(isascii(ch) && isprint(ch))) ch = '.';
+            sprintf(buf, " %02X", b);
+            strcat(hex, buf);
+            ascii[j] = ch;
+        }
+
+        ascii[j] = '\0';
+        if (j < columns) {
+            for (; j < columns; j++) {
+                strcat(hex, "   ");
+            }
+        }
+
+        nsk_printf("%s0x%08X:  %s    %s\n", indent, (int)i, hex, ascii);
+    }
+}
+
+/*************************************************************/
+
+const char* nsk_null_string(const char* str) {
+    return (str == NULL)? "<NULL>" : str;
+}
+
+/*************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/native/nsk_tools.h	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef NSK_TOOLS_DEFINED
+#define NSK_TOOLS_DEFINED
+
+/*************************************************************/
+
+#include <stdarg.h>
+
+/*************************************************************/
+
+/**
+ * Use examples:
+ *
+ *     jfieldID id = NSK_CPP_STUB3(jni,GetFieldID,clazz,name,sig);
+ *
+ *     jvmtiError code = NSK_CPP_STUB0(jvmti,DisposeEnvironment);
+ *
+ */
+
+#define NSK_CPP_STUB1(Func,env)  (*env)->Func(env)
+#define NSK_CPP_STUB2(Func,env,a)  (*env)->Func(env,a)
+#define NSK_CPP_STUB3(Func,env,a,b)  (*env)->Func(env,a,b)
+#define NSK_CPP_STUB4(Func,env,a,b,c)  (*env)->Func(env,a,b,c)
+#define NSK_CPP_STUB5(Func,env,a,b,c,d)  (*env)->Func(env,a,b,c,d)
+#define NSK_CPP_STUB6(Func,env,a,b,c,d,e)  (*env)->Func(env,a,b,c,d,e)
+#define NSK_CPP_STUB7(Func,env,a,b,c,d,e,f)  (*env)->Func(env,a,b,c,d,e,f)
+#define NSK_CPP_STUB8(Func,env,a,b,c,d,e,f,g)  (*env)->Func(env,a,b,c,d,e,f,g)
+#define NSK_CPP_STUB9(Func,env,a,b,c,d,e,f,g,h)  (*env)->Func(env,a,b,c,d,e,f,g,h)
+
+#ifdef __cplusplus
+#ifndef NSK_CPP_STUBS_ENFORCE_C
+#undef NSK_CPP_STUB1
+#undef NSK_CPP_STUB2
+#undef NSK_CPP_STUB3
+#undef NSK_CPP_STUB4
+#undef NSK_CPP_STUB5
+#undef NSK_CPP_STUB6
+#undef NSK_CPP_STUB7
+#undef NSK_CPP_STUB8
+#undef NSK_CPP_STUB9
+#define NSK_CPP_STUB1(Func,env)  env->Func()
+#define NSK_CPP_STUB2(Func,env,a)  env->Func(a)
+#define NSK_CPP_STUB3(Func,env,a,b)  env->Func(a,b)
+#define NSK_CPP_STUB4(Func,env,a,b,c)  env->Func(a,b,c)
+#define NSK_CPP_STUB5(Func,env,a,b,c,d)  env->Func(a,b,c,d)
+#define NSK_CPP_STUB6(Func,env,a,b,c,d,e)  env->Func(a,b,c,d,e)
+#define NSK_CPP_STUB7(Func,env,a,b,c,d,e,f)  env->Func(a,b,c,d,e,f)
+#define NSK_CPP_STUB8(Func,env,a,b,c,d,e,f,g)  env->Func(a,b,c,d,e,f,g)
+#define NSK_CPP_STUB9(Func,env,a,b,c,d,e,f,g,h)  env->Func(a,b,c,d,e,f,g,h)
+#endif
+#endif
+
+/*************************************************************/
+
+/**
+ * Use examples:
+ *
+ *     NSK_DISPLAY("Test started.\n");
+ *     NSK_COMPLAIN("Test FAILED: %s\n",reason);
+ *
+ *
+ */
+
+#define NSK_DISPLAY0(format)  nsk_ldisplay(__FILE__,__LINE__,format)
+#define NSK_DISPLAY1(format,a)  nsk_ldisplay(__FILE__,__LINE__,format,a)
+#define NSK_DISPLAY2(format,a,b)  nsk_ldisplay(__FILE__,__LINE__,format,a,b)
+#define NSK_DISPLAY3(format,a,b,c)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c)
+#define NSK_DISPLAY4(format,a,b,c,d)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d)
+#define NSK_DISPLAY5(format,a,b,c,d,e)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d,e)
+#define NSK_DISPLAY6(format,a,b,c,d,e,f)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d,e,f)
+#define NSK_DISPLAY7(format,a,b,c,d,e,f,g)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d,e,f,g)
+#define NSK_DISPLAY8(format,a,b,c,d,e,f,g,h)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d,e,f,g,h)
+#define NSK_DISPLAY9(format,a,b,c,d,e,f,g,h,i)  nsk_ldisplay(__FILE__,__LINE__,format,a,b,c,d,e,f,g,h,i)
+
+#define NSK_COMPLAIN0(format)  nsk_lcomplain(__FILE__,__LINE__,format)
+#define NSK_COMPLAIN1(format,a)  nsk_lcomplain(__FILE__,__LINE__,format,a)
+#define NSK_COMPLAIN2(format,a,b)  nsk_lcomplain(__FILE__,__LINE__,format,a,b)
+#define NSK_COMPLAIN3(format,a,b,c)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c)
+#define NSK_COMPLAIN4(format,a,b,c,d)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d)
+#define NSK_COMPLAIN5(format,a,b,c,d,e)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d,e)
+#define NSK_COMPLAIN6(format,a,b,c,d,e,f)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d,e,f)
+#define NSK_COMPLAIN7(format,a,b,c,d,e,f,g)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d,e,f,g)
+#define NSK_COMPLAIN8(format,a,b,c,d,e,f,g,h)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d,e,f,g,h)
+#define NSK_COMPLAIN9(format,a,b,c,d,e,f,g,h,i)  nsk_lcomplain(__FILE__,__LINE__,format,a,b,c,d,e,f,g,h,i)
+
+#define NSK_VERIFY(action)  (nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action), \
+                                nsk_lverify(!!(action),__FILE__,__LINE__,"%s\n",#action))
+#define NSK_TRACE(action)   {nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action); \
+                            (void)(action); \
+                            nsk_ltrace(NSK_TRACE_AFTER,__FILE__,__LINE__,"%s\n",#action);}
+#define NSK_BEFORE_TRACE(action) nsk_ltrace(NSK_TRACE_BEFORE,__FILE__,__LINE__,"%s\n",#action); \
+                                 (void)(action)
+
+/*************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NSK_TRUE  1
+#define NSK_FALSE 0
+
+#define NSK_TRACE_NONE    0
+#define NSK_TRACE_BEFORE  1
+#define NSK_TRACE_AFTER   2
+#define NSK_TRACE_ALL     (NSK_TRACE_BEFORE | NSK_TRACE_AFTER)
+
+#define NSK_MAX_COMPLAINS_NON_VERBOSE 665
+
+/**
+ * Mode is verbose iff "verbose" isn't NSK_FALSE.
+ */
+void nsk_setVerboseMode(int verbose);
+int  nsk_getVerboseMode();
+
+/**
+ * Trace mode can be any combination of NSK_TRACE_* flags.
+ */
+void nsk_setTraceMode(int mode);
+int  nsk_getTraceMode();
+
+/**
+ * Display the message if current mode is verbose.
+ */
+void nsk_display(const char format[], ...);
+void nsk_vdisplay(const char format[], va_list args);
+/**
+ * Add a prompt to point the file[] and line location.
+ */
+void nsk_ldisplay(const char file[], int line, const char format[], ...);
+void nsk_lvdisplay(const char file[], int line, const char format[], va_list args);
+
+/**
+ * Complain the error message; add an "ERROR" prompt.
+ * No matter, is current mode verbose or not.
+ */
+void nsk_complain(const char format[], ...);
+void nsk_vcomplain(const char format[], va_list args);
+/**
+ * Add a prompt to point the file[] and line location.
+ */
+void nsk_lcomplain(const char file[], int line, const char format[], ...);
+void nsk_lvcomplain(const char file[], int line, const char format[], va_list args);
+
+/**
+ * Trace executable actions,
+ */
+void nsk_ltrace(int mode, const char file[], int line, const char format[], ...);
+void nsk_lvtrace(int mode, const char file[], int line, const char format[], va_list args);
+
+/**
+ * Complain the message as an error if value==0; return !!value.
+ * Add a prompt to point the file[] and line location.
+ * Display anyway if verbose.
+ */
+int nsk_lverify(int value, const char file[], int line, const char format[], ...);
+
+/**
+ * Same as printf() or vprintf(); but we may redefine this later.
+ */
+int nsk_vprintf(const char format[], va_list args);
+int nsk_printf(const char format[], ...);
+
+/**
+ * Print given bytes array as hex numbers in multiple strings, each
+ * started with 'indent' prefix and offset info, followed by 'columns' bytes
+ * as hex numbers, then followed by the same bytes as ASCII chars where
+ * non-printable chars are replaced by '.', and terminated with new line char.
+ * Typically columns number is 16 and should not be greater than 255.
+ */
+void nsk_printHexBytes(const char indent[], int columns,
+                                    size_t size, const unsigned char bytes[]);
+
+/*************************************************************/
+
+/**
+ * Returns str or "<NULL>" if str is NULL; useful for printing strings.
+ */
+const char* nsk_null_string(const char* str);
+
+/*************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*************************************************************/
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/FinRunner.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package nsk.share.runner;
+
+/**
+ *  Helper that calls System.runFinalization().
+ */
+public class FinRunner implements Runnable {
+        public void run() {
+                System.runFinalization();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/GCRunner.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+/**
+ *  Helper that calls GC.
+ */
+public class GCRunner implements Runnable {
+        public void run() {
+                System.gc();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/MemDiag.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+/**
+ *  Helper that prints memory information.
+ */
+public class MemDiag implements Runnable {
+        private long sleepTime;
+
+        public MemDiag() {
+                this(RunParams.getInstance().getSleepTime());
+        }
+
+        public MemDiag(long sleepTime) {
+                this.sleepTime = sleepTime;
+        }
+
+        public void run() {
+                System.out.println(Runtime.getRuntime().freeMemory());
+                // Ensure that interrupt status is not lost
+                if (Thread.currentThread().isInterrupted())
+                        return;
+                try {
+                        Thread.sleep(sleepTime);
+                } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/MultiRunner.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+import nsk.share.test.ExecutionController;
+
+/**
+ * Interface that defines a way to run several tasks.
+ *
+ * Several implementations are provided.
+ *
+ * @see nsk.share.runner.ThreadsRunner
+ */
+public interface MultiRunner extends Runnable {
+        /**
+         * Add a task.
+         *
+         * @param runnable task
+         */
+        public void add(Runnable runnable);
+
+        /**
+         * Remove a task.
+         *
+         * @param runnable task
+         */
+        public void remove(Runnable runnable);
+
+        /**
+         * Remove all tasks.
+         */
+        public void removeAll();
+
+        /**
+         * Run tasks.
+         */
+        public void run();
+
+        /**
+         * Get status of run.
+         *
+         * @return true if everything is alright, false if there are any errors
+         */
+        public boolean isSuccessful();
+
+        /**
+         * Get execution controller for current thread.
+         *
+         * @returns execution controller for current thread
+         */
+        public ExecutionController getExecutionController();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/MultiRunnerAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+/**
+ * Marker interface for getting MultiRunner.
+ */
+public interface MultiRunnerAware {
+        public void setRunner(MultiRunner runner);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/RunParams.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+import nsk.share.log.Log;
+import nsk.share.test.StressOptions;
+import java.io.PrintStream;
+
+public class RunParams {
+        private StressOptions stressOptions;
+        private long sleepTime = 500;
+        private long iterations = 0;
+        private int numberOfThreads;
+        private long seed = System.currentTimeMillis();
+        private boolean runGCThread = false;
+        private boolean runFinThread = false;
+        private boolean runMemDiagThread = false;
+        private boolean runFinDiagThread = false;
+        private boolean runAllDiagThread = false;
+        private boolean runForever = false;
+        private long threadBlockSize = 64 * 1024 * 1024;
+        private boolean interruptThreads = false;
+
+        public RunParams() {
+                this(new StressOptions());
+        }
+
+        public RunParams(StressOptions stressOptions) {
+                this.stressOptions = stressOptions;
+                numberOfThreads = getMediumLoadThreadsCount();
+        }
+
+        public RunParams(String[] args) {
+                this();
+                parseCommandLine(args);
+        }
+
+        /**
+         *  Get an approximate memory which test should fill.
+         *
+         *  This can be used to adjust the parameters of allocated objects
+         *  to test run environment. Currently it is 3/5 of
+         *  Runtime.getRuntime().maxMemory().
+         */
+        public long getTestMemory() {
+                return 3 * Runtime.getRuntime().maxMemory() / 5;
+        }
+
+        /**
+         * Return memory to use for allocation of threads.
+         *
+         * This is currently 3/4 of getTestMemory();
+         */
+        public long getThreadsMemory() {
+                return 3 * getTestMemory() / 4;
+        }
+
+        public final long getSleepTime() {
+                return sleepTime;
+        }
+
+        public final void setSleepTime(long sleepTime) {
+                this.sleepTime = sleepTime;
+        }
+
+        public final long getIterations() {
+                return iterations;
+        }
+
+        public final void setIterations(long iterations) {
+                if (this.iterations != iterations) {
+                        this.iterations = iterations;
+                        System.out.println("Iterations: " + iterations);
+                }
+        }
+
+        public int getBasicLoadThreadsCount() {
+                int cnt = (int) Math.min(
+                        Integer.MAX_VALUE,
+                        Math.min(
+                                Runtime.getRuntime().availableProcessors(),
+                                Math.round((double) Runtime.getRuntime().maxMemory() / threadBlockSize)
+                        )
+                );
+
+                // cnt could be equal to 0 in case maxMemory is less than threadBlockSize then
+                // so, need to check this
+                return (cnt > 0 ? cnt : 1);
+        }
+
+        public int getMediumLoadThreadsCount() {
+                return 2 * getBasicLoadThreadsCount();
+        }
+
+        public int getHighLoadThreadsCount() {
+                return 100 * getBasicLoadThreadsCount();
+        }
+
+        public final int getNumberOfThreads() {
+                return numberOfThreads * stressOptions.getThreadsFactor();
+        }
+
+        public final void setNumberOfThreads(int numberOfThreads) {
+                this.numberOfThreads = numberOfThreads;
+        }
+
+        public final long getSeed() {
+                return seed;
+        }
+
+        public final void setSeed(long seed) {
+                this.seed = seed;
+        }
+
+        public final boolean isRunGCThread() {
+                return runGCThread;
+        }
+
+        public final void setRunGCThread(boolean runGCThread) {
+                this.runGCThread = runGCThread;
+        }
+
+        public final boolean isRunFinThread() {
+                return runFinThread;
+        }
+
+        public final void setRunFinThread(boolean runFinThread) {
+                this.runFinThread = runFinThread;
+        }
+
+        public final boolean isRunMemDiagThread() {
+                return runMemDiagThread;
+        }
+
+        public final void setRunMemDiagThread(boolean runMemDiagThread) {
+                this.runMemDiagThread = runMemDiagThread;
+        }
+
+        public final boolean isRunFinDiagThread() {
+                return runFinDiagThread;
+        }
+
+        public final void setRunFinDiagThread(boolean runFinDiagThread) {
+                this.runFinDiagThread = runFinDiagThread;
+        }
+
+        public final boolean isRunAllDiagThread() {
+                return runAllDiagThread;
+        }
+
+        public final void setRunAllDiagThread(boolean runAllDiagThread) {
+                this.runAllDiagThread = runAllDiagThread;
+        }
+
+        public final boolean isRunForever() {
+                return runForever;
+        }
+
+        public final void setRunForever(boolean runForever) {
+                this.runForever = runForever;
+        }
+
+        public final boolean isInterruptThreads() {
+                return interruptThreads;
+        }
+
+        public final void setInterruptThreads(boolean interruptThreads) {
+                this.interruptThreads = interruptThreads;
+        }
+
+        public final StressOptions getStressOptions() {
+                return stressOptions;
+        }
+
+        public void parseCommandLine(String[] args) {
+                if (args == null)
+                        return;
+                stressOptions.parseCommandLine(args);
+                for (int i = 0; i < args.length; ++i) {
+                        if (args[i].equals("-f"))
+                                runForever = true;
+                        else if (args[i].equals("-tg"))
+                                runGCThread = true;
+                        else if (args[i].equals("-tf"))
+                                runFinThread = true;
+                        else if (args[i].equals("-Dm"))
+                                runMemDiagThread = true;
+                        else if (args[i].equals("-Dm-"))
+                                runMemDiagThread = false;
+                        else if (args[i].equals("-Df1"))
+                                runFinDiagThread = true;
+                        else if (args[i].equals("-Df"))
+                                runFinDiagThread = true;
+                        else if (args[i].equals("-s"))
+                                seed = Long.parseLong(args[++i]);
+                        else if (args[i].equals("-t"))
+                                numberOfThreads = Integer.parseInt(args[++i]);
+                        else if (args[i].equals("-it"))
+                                interruptThreads = true;
+                        else if (args[i].equals("-iterations"))
+                                iterations = Integer.parseInt(args[++i]);
+                }
+                printConfig(System.out);
+        }
+
+        public void prinUsage() {
+        }
+
+        public void printConfig(PrintStream out) {
+                stressOptions.printInfo(out);
+                out.println("Max memory: " + Runtime.getRuntime().maxMemory());
+                out.println("Sleep time: " + sleepTime);
+                out.println("Iterations: " + iterations);
+                out.println("Number of threads: " + numberOfThreads);
+                out.println("Seed: " + seed);
+                out.println("Run GC thread: " + runGCThread);
+                out.println("Run mem diag thread: " + runMemDiagThread);
+                out.println("Run forever: " + runForever);
+        }
+
+        public void logConfig(Log log) {
+                log.debug("Max memory: " + Runtime.getRuntime().maxMemory());
+                log.debug("Sleep time: " + sleepTime);
+                log.debug("Iterations: " + iterations);
+                log.debug("Number of threads: " + numberOfThreads);
+                log.debug("Seed: " + seed);
+                log.debug("Run GC thread: " + runGCThread);
+                log.debug("Run mem diag thread: " + runMemDiagThread);
+                log.debug("Run forever: " + runForever);
+        }
+
+        private static RunParams instance;
+
+        public static RunParams getInstance() {
+                synchronized (RunParams.class) {
+                        if (instance == null)
+                                instance = new RunParams();
+                        return instance;
+                }
+        }
+
+        public static void setInstance(RunParams runParams) {
+                synchronized (RunParams.class) {
+                        instance = runParams;
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/RunParamsAware.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.runner;
+
+/**
+ * Marker interface to signify that run params are needed.
+ */
+public interface RunParamsAware {
+        public void setRunParams(RunParams runParams);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.runner;
+
+import nsk.share.Wicket;
+import nsk.share.gc.OOMStress;
+import nsk.share.log.*;
+import nsk.share.test.Stresser;
+import nsk.share.test.ExecutionController;
+import nsk.share.TestBug;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *  Helper to assist in running threads.
+ *
+ *  This class starts a number of threads which run some tasks in cycle.
+ *  They exit after some time or after some iterations as
+ *  determined by RunParams.
+ */
+public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware {
+
+    private Log log;
+    private RunParams runParams;
+    private List<Runnable> runnables = new ArrayList<Runnable>();
+    private List<ManagedThread> threads = new ArrayList<ManagedThread>();
+    private Wicket wicket = new Wicket();
+    private Wicket finished;
+    private boolean started = false;
+    private boolean successful = true;
+
+    public ThreadsRunner() {
+        this(RunParams.getInstance());
+    }
+
+    public ThreadsRunner(RunParams runParams) {
+        setRunParams(runParams);
+    }
+
+    public final void setLog(Log log) {
+        this.log = log;
+    }
+
+    private class ManagedThread extends Thread {
+
+        private Stresser stresser;
+        private Throwable exception;
+        private Runnable test;
+        private boolean shouldWait;
+
+        public ManagedThread(Runnable test) {
+            super(test.toString());
+            this.test = test;
+            this.shouldWait = true;
+            this.stresser = new Stresser(this.getName(), runParams.getStressOptions());
+        }
+
+        public void run() {
+            wicket.waitFor();
+            try {
+                stresser.start(runParams.getIterations());
+                while (!this.isInterrupted() && stresser.iteration()) {
+                    test.run();
+                    yield();
+                }
+                waitForOtherThreads();
+            } catch (OutOfMemoryError oom) {
+                waitForOtherThreads();
+                if (test instanceof OOMStress) {
+                    // Test stressing OOM, not a failure.
+                    log.info("Caught OutOfMemoryError in OOM stress test, omitting exception.");
+                } else {
+                    failWithException(oom);
+                }
+            } catch (Throwable t) {
+                waitForOtherThreads();
+                failWithException(t);
+            } finally {
+                stresser.finish();
+            }
+        }
+
+        private void waitForOtherThreads() {
+            if (shouldWait) {
+                shouldWait = false;
+                finished.unlock();
+                finished.waitFor();
+            } else {
+                throw new TestBug("Waiting a second time is not premitted");
+            }
+        }
+
+        private void failWithException(Throwable t) {
+            log.debug("Exception in ");
+            log.debug(test);
+            log.debug(t);
+            exception = t;
+        }
+
+        public void forceFinish() {
+            stresser.forceFinish();
+            if (runParams.isInterruptThreads()) {
+                log.debug("Interrupting: " + this);
+                this.interrupt();
+            }
+        }
+
+        public final Throwable getException() {
+            return exception;
+        }
+
+        public final ExecutionController getExecutionController() {
+            return stresser;
+        }
+    }
+
+    public void add(Runnable runnable) {
+        runnables.add(runnable);
+    }
+
+    public void remove(Runnable runnable) {
+        runnables.remove(runnable);
+    }
+
+    public void removeAll() {
+        runnables.clear();
+    }
+
+    private Runnable get(int index) {
+        return (Runnable) runnables.get(index);
+    }
+
+    public Thread getThread(int index) {
+        return threads.get(index);
+    }
+
+    private int getCount() {
+        return runnables.size();
+    }
+
+    private void prepare() {
+    }
+
+    private void create() {
+        int threadCount = runnables.size();
+        finished = new Wicket(threadCount);
+        for (int i = 0; i < threadCount; ++i) {
+            threads.add(new ManagedThread(get(i)));
+        }
+    }
+
+    /**
+     * Start threads that run the tasks.
+     */
+    public void start() {
+        if (started) {
+            return;
+        }
+        create();
+        prepare();
+        for (int i = 0; i < threads.size(); ++i) {
+            Thread t = (Thread) threads.get(i);
+            log.debug("Starting " + t);
+            t.start();
+        }
+        wicket.unlock();
+        started = true;
+    }
+
+    /**
+     * Stop threads that run the tasks.
+     */
+    public void forceFinish() {
+        log.info("Forcing threads to finish");
+        for (int i = 0; i < threads.size(); i++) {
+            ManagedThread thread = threads.get(i);
+            thread.forceFinish();
+        }
+    }
+
+    /**
+     * Join threads that run the tasks.
+     */
+    public void join() throws InterruptedException {
+        for (int i = 0; i < threads.size(); ++i) {
+            Thread t = (Thread) threads.get(i);
+            //log.debug("Joining " + t);
+            t.join();
+        }
+    }
+
+    private int dumpFailures() {
+        int n = 0;
+        for (int i = 0; i < threads.size(); i++) {
+            ManagedThread thread = threads.get(i);
+            Throwable exception = thread.getException();
+            if (exception != null) {
+                if (n == 0) {
+                    log.error("Failures summary:");
+                }
+                ++n;
+                log.error(exception);
+            }
+        }
+        if (n == 0) {
+            log.info("No unexpected exceptions/errors are thrown");
+        }
+        return n;
+    }
+
+    private ManagedThread findManagedThread(Thread t) {
+        for (int i = 0; i < threads.size(); i++) {
+            ManagedThread mt = threads.get(i);
+            if (mt == t) {
+                return mt;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Run threads as determined by RunParams.
+     *
+     * Start threads, run for some time or for some number of iterations,
+     * then join and report if there were any exceptions.
+     *
+     * This method may additionally run other threads (as determined by RunParams):
+     * - thread that does System.gc() in cycle, @see GCRunner
+     * - thread that prints memory information in cycle, @see MemDiag
+     * - thread that prints information about FinMemoryObject's in cycle, @see FinDiag
+     * - thread that prints information about AllMemoryObject's in cycle, @see AllDiag
+     *
+     * @return true if there were no exceptions, false otherwise
+     */
+    public void run() {
+        if (runParams.isRunGCThread()) {
+            add(new GCRunner());
+        }
+        if (runParams.isRunFinThread()) {
+            add(new FinRunner());
+        }
+        if (runParams.isRunMemDiagThread()) {
+            add(new MemDiag());
+        }
+        try {
+            start();
+            join();
+            successful = dumpFailures() == 0;
+        } catch (Throwable t) {
+            log.info("Unexpected exception during the run.");
+            log.info(t);
+            successful = false;
+        }
+    }
+
+    public boolean isSuccessful() {
+        return successful;
+    }
+
+    public ExecutionController getExecutionController() {
+        Thread ct = Thread.currentThread();
+        ManagedThread t = findManagedThread(ct);
+        if (t != null) {
+            return t.getExecutionController();
+        } else {
+            throw new TestBug("Unable to find managed thread for thread (this method should be called from one of managed threads): " + ct);
+        }
+    }
+
+    public void runForever() {
+        start();
+    }
+
+    public final void setRunParams(RunParams runParams) {
+        this.runParams = runParams;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/sysdict/ClassLoadersBTree.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.sysdict;
+
+import nsk.share.*;
+
+/**
+ * A binary tree of class loaders.
+ *
+ * @see TreeNodesDenotation
+ */
+public class ClassLoadersBTree {
+    /**
+     * Cannot instantiate while a tree root and height
+     * are not specified.
+     *
+     * @see #ClassLoadersBTree(ClassLoader,int)
+     */
+    protected ClassLoadersBTree() {
+    }
+
+    /**
+     * Given the <tt>root</tt> loader, instantiate a binary tree
+     * of loaders up to the given tree <tt>height</tt>.
+     *
+     * @see #getHeight()
+     * @see #getRoot()
+     * @see #getLoader(String)
+     * @see #getLoader(int,int)
+     */
+    public ClassLoadersBTree(ClassLoader root, int height) {
+        if (height < 1)
+            throw new IllegalArgumentException("wrong height: " + height);
+        loaders = new ClassLoader [ height ] [];
+        for (int level=0; level<height; level++)
+            loaders[level] = new ClassLoader [1 << level];
+        loaders[0][0] = root;
+        generateSubtree("");
+    }
+    private void generateSubtree(String name) {
+        int level = name.length();
+        int height = loaders.length;
+        if (level+1 == height)
+            return;
+        String nameL = name + "L";
+        String nameR = name + "R";
+        int[] index  = denotation.indexFor(name);
+        int[] indexL = denotation.indexFor(nameL);
+        int[] indexR = denotation.indexFor(nameR);
+        // assertion: index[0]  == level
+        // assertion: indexL[0] == indexR[0] == level+1
+        int item  = index[1];
+        int itemL = indexL[1];
+        int itemR = indexR[1];
+        ClassLoader parent = loaders[level][item];
+        ClassLoader childL = new DummyClassLoader(parent);
+        ClassLoader childR = new DummyClassLoader(parent); // another item
+        loaders[level+1][itemL] = childL;
+        loaders[level+1][itemR] = childR;
+        generateSubtree(nameL);
+        generateSubtree(nameR);
+    }
+
+    private ClassLoader loaders[][]; // loaders[0][0] is root
+    private Denotation denotation = new TreeNodesDenotation();
+
+    /**
+     * Return the loader found at the given <tt>level</tt> of
+     * this loaders tree, and having the given <tt>item</tt>
+     * number at the enumeration of that <tt>level</tt>.
+     *
+     * <p>The value of <tt>level</tt> must be from <tt>0</tt>
+     * to <tt>getHeight()-1</tt>, and the <tt>item</tt> number
+     * must be from <tt>0</tt> to <tt>2<sup>level</sup>-1</tt>.
+     *
+     * @see #getHeight()
+     * @see #getRoot()
+     * @see #getLoader(String)
+     */
+    public ClassLoader getLoader(int level, int item) {
+        return loaders[level][item];
+    }
+
+    /**
+     * Return the loader having the giving <tt>name</tt> at
+     * the standard denotation of binary tree nodes.
+     *
+     * @see #getHeight()
+     * @see #getRoot()
+     * @see #getLoader(int,int)
+     */
+    public ClassLoader getLoader(String name) {
+        int[] index = denotation.indexFor(name);
+        int level = index[0];
+        int item  = index[1];
+        return loaders[level][item];
+    }
+
+    /**
+     * Return the tree's height.
+     *
+     * @see #ClassLoadersBTree(ClassLoader,int)
+     * @see #getLoader(int,int)
+     * @see #getLoader(String)
+     */
+    public int getHeight() {
+        return loaders.length;
+    }
+
+    /**
+     * Return the tree's root loader.
+     *
+     * @see #ClassLoadersBTree(ClassLoader,int)
+     * @see #getLoader(int,int)
+     * @see #getLoader(String)
+     */
+    public ClassLoader getRoot() {
+        return loaders[0][0];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/sysdict/ClassLoadersChain.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.sysdict;
+
+import nsk.share.*;
+
+/**
+ * A chain of class loaders. Imagine a chain as a tower
+ * growing downstairs: the 0<sup>th</sup> level is the
+ * root, and a level n+1 loader has the n<sup>th</sup>
+ * loader as the parent.
+ */
+public class ClassLoadersChain {
+    /**
+     * Cannot instantiate while a chain root and height
+     * are not specified.
+     *
+     * @see #ClassLoadersChain(ClassLoader,int)
+     */
+    protected ClassLoadersChain() {
+    }
+
+    /**
+     * Given the <tt>root</tt> loader, instantiate a chain
+     * of loaders up to the given <tt>height</tt>.
+     *
+     * @see #getHeight()
+     * @see #getRoot()
+     * @see #getLoader(int)
+     */
+    public ClassLoadersChain(ClassLoader root, int height) {
+        if (height < 1)
+            throw new IllegalArgumentException("wrong height: " + height);
+        loaders = new ClassLoader [ height ];
+        loaders[0] = root;
+        for (int i=1; i<height; i++)
+            loaders[i] = new DummyClassLoader(loaders[i-1]);
+    }
+
+    private ClassLoader loaders[]; // loaders[0] is the root
+
+    /**
+     * Return the loader found at the given <tt>level</tt>.
+     * The value of <tt>level</tt> must be from <tt>0</tt>
+     * to <tt>getHeight()-1</tt>.
+     *
+     * @see #getHeight()
+     * @see #getRoot()
+     */
+    public ClassLoader getLoader(int level) {
+        return loaders[level];
+    }
+
+    /**
+     * Return the chain's height.
+     *
+     * @see #ClassLoadersChain(ClassLoader,int)
+     * @see #getLoader(int)
+     */
+    public int getHeight() {
+        return loaders.length;
+    }
+
+    /**
+     * Return the chain's root loader.
+     *
+     * @see #ClassLoadersChain(ClassLoader,int)
+     * @see #getLoader(int)
+     */
+    public ClassLoader getRoot() {
+        return loaders[0];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Dumpable.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+import nsk.share.log.Log;
+
+public interface Dumpable {
+        public void dump(Log log);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/ExecutionController.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+public interface ExecutionController {
+        public void start(long stdIterations);
+        public boolean iteration();
+        public boolean continueExecution();
+        public long getIteration();
+        public void finish();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Initializable.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+/**
+ * Marker interface for initialization.
+ */
+public interface Initializable {
+        public void initialize();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyFormatString.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+public class LazyFormatString {
+
+    private String format;
+    private Object[] args;
+
+    public LazyFormatString(String format, Object... args) {
+        this.format = format;
+        this.args = args;
+    }
+
+    @Override
+    public String toString() {
+        return String.format(format, args);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyIntArrayToString.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+import java.util.Arrays;
+
+public class LazyIntArrayToString {
+
+    private int[] array;
+
+    public LazyIntArrayToString(int[] array) {
+        this.array = array;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(array);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/LazyObjectArrayToString.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+import java.util.Arrays;
+
+public class LazyObjectArrayToString {
+
+    private Object[] array;
+
+    public LazyObjectArrayToString(Object[] array) {
+        this.array = array;
+    }
+
+    @Override
+    public String toString() {
+        return Arrays.toString(array);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/LocalRandom.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+import java.util.concurrent.ThreadLocalRandom;
+import nsk.share.TestFailure;
+
+/**
+ * Utility class which encapsulates all useful static methods.
+ */
+public class LocalRandom {
+    private static int minPauseTime = 3000;
+    private static int maxPauseTime = 5000;
+    private static int maxRandomCount = 65536;
+
+    /*
+     * Return next random double number.
+     *
+     * @return random double
+     */
+    public static double random() {
+        return ThreadLocalRandom.current().nextDouble();
+    }
+
+    public static double nextDouble() {
+        return ThreadLocalRandom.current().nextDouble();
+    }
+
+    public static byte nextByte() {
+        return (byte) nextInt(Byte.MIN_VALUE, Byte.MAX_VALUE);
+    }
+
+    public static char nextChar() {
+        return (char) nextInt(Character.MIN_VALUE, Character.MAX_VALUE);
+    }
+
+    public static short nextShort() {
+        return (short) nextInt(Short.MIN_VALUE, Short.MAX_VALUE);
+    }
+
+    public static boolean nextBoolean() {
+        return ThreadLocalRandom.current().nextBoolean();
+    }
+
+    public static void nextBytes(byte[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        byte hash = 0;
+        byte b;
+        for (int i = 0; i < arr.length - k; i += k) {
+            b = nextByte();
+            arr[i] = b;
+            hash ^= b;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(byte[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        byte hash = 0;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != 0) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextShorts(short[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        short hash = 0;
+        short s;
+        for (int i = 0; i < arr.length - k; i += k) {
+            s = nextShort();
+            arr[i] = s;
+            hash ^= s;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(short[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        short hash = 0;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != 0) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextChars(char[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        char hash = 0;
+        char c;
+        for (int i = 0; i < arr.length - k; i += k) {
+            c = nextChar();
+            arr[i] = c;
+            hash ^= c;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(char[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        char hash = 0;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != 0) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextInts(int[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        int hash = 0;
+        int in;
+        for (int i = 0; i < arr.length - k; i += k) {
+            in = nextInt();
+            hash ^= in;
+            arr[i] = in;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(int[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        int hash = 0;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != 0) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextBooleans(boolean[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        boolean hash = false;
+        boolean b;
+        for (int i = 0; i < arr.length - k; i += k) {
+            b = nextBoolean();
+            hash ^= b;
+            arr[i] = b;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(boolean[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        boolean hash = false;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != false) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextLongs(long[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        long hash = 0;
+        long l;
+        for (int i = 0; i < arr.length - k; i += k) {
+            l = nextLong();
+            hash ^= l;
+            arr[i] = l;
+        }
+        arr[arr.length - k] = hash;
+    }
+
+    public static void validate(long[] arr) {
+        int k = Math.max(1, arr.length / maxRandomCount);
+        long hash = 0;
+        for (int i = 0; i < arr.length; i += k) {
+            hash ^= arr[i];
+        }
+        if (hash != 0) {
+            throw new TestFailure(
+                    "Validation failure: " + arr.getClass() + " hash: " + hash);
+        }
+    }
+
+    public static void nextFloats(float[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        for (int i = 0; i < arr.length - k; i += k) {
+            arr[i] = nextFloat();
+        }
+    }
+
+    public static void validate(float[] arr) {
+    }
+
+    public static void nextDoubles(double[] arr) {
+        if (arr.length == 0) {
+            return;
+        }
+        int k = Math.max(1, arr.length / maxRandomCount);
+        for (int i = 0; i < arr.length - k; i += k) {
+            arr[i] = nextDouble();
+        }
+    }
+
+    public static void validate(double[] arr) {
+    }
+
+    public static int nextInt() {
+        return ThreadLocalRandom.current().nextInt();
+    }
+
+    /**
+     * Return next integer value from 0..n range.
+     *
+     * @param n maximum value
+     * @return random integer
+     */
+    public static int nextInt(int n) {
+        return ThreadLocalRandom.current().nextInt(n);
+    }
+
+    public static long nextLong() {
+        return ThreadLocalRandom.current().nextLong();
+    }
+
+    /**
+     * Return next random integer from min..max range.
+     *
+     * @param min minimum value
+     * @param max maximum value
+     * @return random integer
+     */
+    public static int nextInt(int min, int max) {
+        return min + nextInt(max - min);
+    }
+
+    /**
+     * Return next random float number.
+     *
+     * @return random double
+     */
+    public static float nextFloat() {
+        return ThreadLocalRandom.current().nextFloat();
+    }
+
+    /**
+     * Return random pause time.
+     */
+    public static long randomPauseTime() {
+        return nextInt(minPauseTime, maxPauseTime);
+    }
+
+    /**
+     * Set minimum pause time.
+     *
+     * @param minPauseTime minimum pause time
+     */
+    public static void setMinPauseTime(int minPauseTime) {
+        LocalRandom.minPauseTime = minPauseTime;
+    }
+
+    /**
+     * Set maximum pause time.
+     *
+     * @param maxPauseTime maximum pause time
+     */
+    public static void setMaxPauseTime(int maxPauseTime) {
+        LocalRandom.maxPauseTime = maxPauseTime;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/StressOptions.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+import java.io.PrintStream;
+import vm.share.options.Option;
+
+/**
+ * Options for stress tests.
+ *
+ * The following options may be configured:
+ *
+ *   -stressTime [time] execution time in seconds
+ *   -stressIterationsFactor [factor] iterations factor.
+ *   The actual number of iterations is obtained by multiplying standard
+ *   number of iterations (which is defined by the test itself) and this factor.
+ *   -stressThreadsFactor [factor] number of threads factor
+ *   The actual number of threads is determined by multiplying standard
+ *   number of threads (which is determined by test itself and may also depend
+ *   on machine configuration) and this factor.
+ */
+public class StressOptions {
+    /**
+     * This enum contains names of stress options
+     */
+    public static enum StressOptionsParam {
+        stressTime,
+        stressIterationsFactor,
+        stressThreadsFactor,
+        stressRunsFactor,
+        stressDebug,
+        stressDebugDetailed,
+    }
+
+    /* Execution time in seconds */
+    @Option(name = "stressTime", default_value = "60", description = "Stress execution time in seconds")
+    private long time;
+
+    /* Iterations factor */
+    @Option(name = "stressIterationsFactor", default_value = "1", description = "Stress iterations factor")
+    private int iterationsFactor;
+
+    /* Number of threads factor */
+    @Option(name = "stressThreadsFactor", default_value = "1", description = "Stress threads factor")
+    private int threadsFactor;
+
+    @Option(name = "stressRunsFactor", default_value = "1", description = "Times to re-run the test (if supported by the test)")
+    private int runsFactor;
+
+    /* Debug stress execution */
+    @Option(name = "stressDebugEnabled", default_value = "false", description = "Stress debug execution enabled")
+    private boolean debugEnabled = false;
+
+    /* Detailed stressExecution */
+    @Option(name = "stressDebugDetailed", default_value = "false", description = "Stress debug detailed enabled")
+    private boolean debugDetailed = false;
+
+    /**
+     * Create StressOptions with default settings.
+     */
+    public StressOptions() {
+        time = 60;
+        iterationsFactor = 1;
+        threadsFactor = 1;
+        runsFactor = 1;
+    }
+
+    /**
+     * Create StressOptions configured from command line arguments.
+     *
+     * @param arg arguments
+     */
+    public StressOptions(String[] args) {
+        this();
+        parseCommandLine(args);
+    }
+
+    /**
+     * Create stresser with same parameters as another.
+     *
+     * @param other another instance of StressOptions
+     */
+    public StressOptions(StressOptions other) {
+        this.time = other.time;
+        this.iterationsFactor = other.iterationsFactor;
+        this.threadsFactor = other.threadsFactor;
+        this.runsFactor = other.runsFactor;
+    }
+
+    public static boolean isValidStressOption(String option) {
+        for (int i = 0; i < StressOptions.StressOptionsParam.values().length; i++) {
+            if (option.equals(StressOptions.StressOptionsParam.values()[i].name()))
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Parse command line options related to stress.
+     *
+     * Other options are ignored.
+     *
+     * @param args arguments
+     */
+    public void parseCommandLine(String[] args) {
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i];
+            String value = null;
+
+            int eqPos = arg.indexOf('=');
+            if (eqPos != -1) {
+                value = arg.substring(eqPos + 1);
+                arg = arg.substring(0, eqPos);
+            }
+
+            if (arg.equals("-stressTime")) {
+                try {
+                    if (value == null) {
+                        if (++i >= args.length)
+                            error("Missing value of -stressTime parameter");
+                        value = args[i];
+                    }
+                    time = Long.parseLong(value);
+                    if (time < 0) {
+                        error("Invalid value of -stressTime parameter: " + time);
+                    }
+                } catch (NumberFormatException e) {
+                    error("Invalid value of -stressTime parameter: " + value);
+                }
+            } else if (arg.equals("-stressIterationsFactor")) {
+                try {
+                    if ( value == null ) {
+                        if (++i >= args.length) {
+                            error("Missing value of -stressIterationsFactor parameter");
+                        }
+                        value = args[i];
+                    }
+                    iterationsFactor = Integer.parseInt(value);
+                    if (iterationsFactor <= 0) {
+                        error("Invalid value of -stressIterationsFactor parameter: " + threadsFactor);
+                    }
+                } catch (NumberFormatException e) {
+                    error("Invalid value of -stressIterationsFactor parameter: " + value);
+                }
+            } else if (arg.equals("-stressThreadsFactor")) {
+                try {
+                    if ( value == null ) {
+                        if (++i >= args.length) {
+                            error("Missing value of -stressThreadsFactor parameter");
+                        }
+                        value = args[i];
+                    }
+                    threadsFactor = Integer.parseInt(value);
+                    if (threadsFactor <= 0) {
+                        error("Invalid value of -stressThreadsFactor parameter: " + threadsFactor);
+                    }
+                } catch (NumberFormatException e) {
+                    error("Invalid value of -stressThreadsFactor parameter: " + value);
+                }
+            } else if (arg.equals("-stressRunsFactor")) {
+                try {
+                    if (value == null) {
+                        if (++i >= args.length) {
+                            error("Missing value of -stressRunsFactor parameter");
+                        }
+                        value = args[i];
+                    }
+                    runsFactor = Integer.parseInt(value);
+                    if (runsFactor <= 0) {
+                        error("Invalid value of -stressRunsFactor parameter: " + threadsFactor);
+                    }
+                } catch (NumberFormatException e) {
+                    error("Invalid value of -stressRunsFactor parameter: " + value);
+                }
+            } else if (arg.equals("-stressDebug")) {
+                debugEnabled = true;
+            } else if (arg.equals("-stressDebugDetailed")) {
+                debugDetailed = true;
+            }
+
+            ++i;
+        }
+    }
+
+    /**
+     * Display information about stress options.
+     *
+     * @param out output stream
+     */
+    public void printInfo(PrintStream out) {
+        out.println("Stress time: " + time + " seconds");
+        out.println("Stress iterations factor: " + iterationsFactor);
+        out.println("Stress threads factor: " + threadsFactor);
+        out.println("Stress runs factor: " + runsFactor);
+    }
+
+    private void error(String msg) {
+        throw new IllegalArgumentException(msg);
+    }
+
+    /**
+     * Obtain execution time in seconds.
+     *
+     * @return time
+     */
+    public long getTime() {
+        return time;
+    }
+
+    /**
+     * Obtain iterations factor.
+     *
+     * @return iterations factor
+     */
+    public int getIterationsFactor() {
+        return iterationsFactor;
+    }
+
+    /**
+     * Obtain threads factor.
+     *
+     * @return threads factor
+     */
+    public int getThreadsFactor() {
+        return threadsFactor;
+    }
+
+    /**
+     * Obtain runs factor.
+     *
+     * @return runs factor
+     */
+    public int getRunsFactor() {
+        return runsFactor;
+    }
+
+    /**
+     * Determine if debugging of stress execution is set.
+     *
+     * @return true if debugging stress execution
+     */
+    public boolean isDebugEnabled() {
+        return debugEnabled;
+    }
+
+    /**
+     * Determine if detailed debugging of stress execution is set.
+     *
+     * @return true if detailed debugging is enabled
+     */
+    public boolean isDebugDetailed() {
+        return debugDetailed;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Stresser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+import java.io.PrintStream;
+import nsk.share.TestBug;
+
+/**
+ * Support class for implementing configurable stress execution.
+ *
+ * This class is intended to be used in one thread
+ *
+ * <code>
+ * Stresser stresser = new Stresser(stressOptions);
+ *
+ * try {
+ *      stresser.start(100);
+ *      while (stresser.iteration()) {
+ *              ...
+ *      }
+ * } finally {
+ *      stresser.finish();
+ * }
+ * </code>
+ *
+ * Standard number of iterations (integer parameter to start() method) is
+ * defined by particular test itself. It may be different for different tests
+ * because average execution time of one iteration may be different.
+ * This is value which is enough to do what test intends to do and it should
+ * also give average execution time on most configurations less than
+ * standard value of stressTime parameter (60 seconds).
+ *
+ * @see nsk.share.test.StressOptions for explanation of stress options.
+ */
+public class Stresser implements ExecutionController {
+
+    private StressOptions options;
+    private String name;
+    private long maxIterations;
+    private long iterations;
+    private long startTime;
+    private long finishTime;
+    private long currentTime;
+    private PrintStream defaultOutput = System.out;
+
+    /*
+     * Flag which indicates that execution is finished.
+     * Volatile, because another thread might read this variable.
+     */
+    private volatile boolean finished;
+
+    /*
+     * Flag which indicates that execution should be forced to finish.
+     * Volatile, because another thread might set this variable.
+     */
+    private volatile boolean forceFinish;
+
+    /**
+     * Creates stresser with default settings.
+     */
+    public Stresser() {
+        this(new StressOptions());
+    }
+
+    /**
+     * Creates stresser with given options.
+     *
+     * @param options stress options
+     */
+    public Stresser(StressOptions options) {
+        setOptions(options);
+    }
+
+    /**
+     * Create stresser configured from command line arguments.
+     *
+     * @param arg arguments
+     */
+    public Stresser(String[] args) {
+        this(new StressOptions(args));
+    }
+
+    /**
+     * Creates stresser configured from command line arguments and
+     * sets its output stream to a given one
+     *
+     * @param arg arguments
+     * @param out default output stream
+     */
+    public Stresser(String[] args, PrintStream out) {
+        this(new StressOptions(args));
+        setDefaultOutput(out);
+    }
+
+    /**
+     * Creates stresser with default options and given name.
+     *
+     * @param name stresser name
+     */
+    public Stresser(String name) {
+        this();
+        setName(name);
+    }
+
+    /**
+     * Creates stresser with given name and options.
+     *
+     * @param name stresser name
+     * @param options stress options
+     */
+    public Stresser(String name, StressOptions options) {
+        this(options);
+        setName(name);
+    }
+
+    /**
+     * Creates stresser with given name from command line arguments.
+     *
+     * @param name stresser name
+     * @param args arguments
+     */
+    public Stresser(String name, String[] args) {
+        this(args);
+        setName(name);
+    }
+
+    /**
+     * Sets default output stream for printing debug messages.
+     * Initially it is set to System.out.
+     *
+     * @param out The stream to print to
+     */
+    public void setDefaultOutput(PrintStream out) {
+        defaultOutput = out;
+    }
+
+    /**
+     * Displays information about stress options.
+     */
+    public void printStressOptions(PrintStream out) {
+        options.printInfo(out);
+    }
+
+    /**
+     * Displays information about this stresser.
+     *
+     * @param out output stream
+     */
+    public void printStressInfo(PrintStream out) {
+        println(out, "Stress time: " + options.getTime() + " seconds");
+        println(out, "Iterations: " + maxIterations);
+    }
+
+    /**
+     * Displays information about this particular execution
+     * of this stresser.
+     *
+     * @param out output stream
+     */
+    public void printExecutionInfo(PrintStream out) {
+        println(out, "Completed iterations: " + iterations);
+        println(out, "Execution time: " + (currentTime - startTime) + " seconds");
+        if (!finished) {
+            println(out, "Execution is not finished yet");
+        } else if (forceFinish) {
+            println(out, "Execution was forced to finish");
+        } else if (maxIterations != 0 && iterations >= maxIterations) {
+            println(out, "Execution finished because number of iterations was exceeded: " + iterations + " >= " + maxIterations);
+        } else if (finishTime != 0 && currentTime >= finishTime) {
+            println(out, "Execution finished because time was exceeded: " + (currentTime - startTime) + " >= " + (finishTime - startTime));
+        }
+    }
+
+    private void println(PrintStream out, String s) {
+        if (name != null) {
+            out.print(name);
+            out.print(": ");
+        }
+        out.println(s);
+        out.flush();
+    }
+
+    /**
+     * Starts stress execution.
+     *
+     * @param stdIterations standard number of iterations.
+     */
+    public void start(long stdIterations) {
+        maxIterations = stdIterations * options.getIterationsFactor();
+        iterations = 0;
+        long stressTime = options.getTime();
+        startTime = System.currentTimeMillis();
+        if (stressTime == 0) {
+            finishTime = 0;
+        } else {
+            finishTime = startTime + stressTime * 1000;
+        }
+        finished = false;
+        forceFinish = false;
+        if (options.isDebugEnabled()) {
+            println(defaultOutput, "Starting stress execution: " + stdIterations);
+            printStressInfo(defaultOutput);
+        }
+    }
+
+    /**
+     * Finishes stress execution.
+     *
+     * This method should be called from the thread where
+     * execution is performed after the loop. It is also
+     * recommended that this method is called from
+     * finally {} block.
+     */
+    public void finish() {
+        currentTime = System.currentTimeMillis();
+        finished = true;
+        if (options.isDebugEnabled()) {
+            printExecutionInfo(defaultOutput);
+        }
+    }
+
+    /**
+     * Forces execution to finish.
+     *
+     * This method may be called from other thread.
+     */
+    public void forceFinish() {
+        forceFinish = true;
+    }
+
+    /**
+     * Marks the beginning of new iteration.
+     *
+     * @return true if execution needs to continue
+     */
+    public boolean iteration() {
+        ++iterations;
+        if (options.isDebugDetailed()) {
+            printExecutionInfo(defaultOutput);
+        }
+        return continueExecution();
+    }
+
+    /**
+     * Checks if execution needs to continue. This does not mark new iteration.
+     *
+     * @return true if execution needs to continue
+     */
+    public boolean continueExecution() {
+        currentTime = System.currentTimeMillis();
+        if (startTime == 0) {
+            throw new TestBug("Stresser is not started.");
+        }
+        return !forceFinish
+                && !finished
+                && (maxIterations == 0 || iterations < maxIterations)
+                && (finishTime == 0 || currentTime < finishTime);
+    }
+
+    /**
+     * Obtains current iteration number.
+     *
+     * @return current iteration
+     */
+    public long getIteration() {
+        return iterations;
+    }
+
+    /**
+     * Obtains maximum number of iterations.
+     *
+     * @return max number of iterations
+     */
+    public long getMaxIterations() {
+        return maxIterations;
+    }
+
+    public long getIterationsLeft() {
+        if (iterations >= maxIterations) {
+            return 0;
+        } else {
+            return maxIterations - iterations;
+        }
+    }
+
+    /**
+     * Obtains time passed from start of stress execution in milliseconds.
+     *
+     * @return time
+     */
+    public long getExecutionTime() {
+        return System.currentTimeMillis() - startTime;
+    }
+
+    /**
+     * Obtains time left till end of execution in milliseconds.
+     *
+     * @return time
+     */
+    public long getTimeLeft() {
+        long current = System.currentTimeMillis();
+        if (current >= finishTime) {
+            return 0;
+        } else {
+            return finishTime - current;
+        }
+    }
+
+    /**
+     * Sets stress options for this stresser.
+     *
+     * @param options stress options
+     */
+    public void setOptions(StressOptions options) {
+        this.options = options;
+    }
+
+    /**
+     * Sets name of this stresser.
+     *
+     * @param name name of stresser
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Obtains name of this stresser.
+     */
+    public String getName() {
+        return name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Test.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+/**
+ * Test marker interface.
+ */
+public interface Test extends Runnable {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/TestBase.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+import nsk.share.log.Log;
+import nsk.share.log.LogAware;
+import nsk.share.Consts;
+import vm.share.options.OptionSupport;
+import vm.share.options.Option;
+import vm.share.options.Options;
+
+public abstract class TestBase implements Test, LogAware, TestExitCode {
+        @Option
+        protected Log log;
+        protected volatile int exitCode = 0;
+
+        public final void setLog(Log log) {
+                this.log = log;
+        }
+
+        public final int getExitCode() {
+                return exitCode;
+        }
+
+        public final void setExitCode(int exitCode) {
+                this.exitCode = exitCode;
+        }
+
+        public final void setFailed(boolean failed) {
+                setExitCode(Consts.JCK_STATUS_BASE + (failed ? Consts.TEST_FAILED : Consts.TEST_PASSED));
+        }
+
+        public final boolean isFailed() {
+                return exitCode != 0 && exitCode != 95;
+        }
+
+        public static void runTest(TestBase test, String[] args) {
+                OptionSupport.setup(test, args);
+                test.run();
+                int exitCode = test.getExitCode();
+                if (exitCode != 0)
+                        System.exit(exitCode);
+                else
+                        System.exit(Consts.JCK_STATUS_BASE + Consts.TEST_PASSED);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/TestExitCode.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+/**
+ * Marker interface to signify that test needs to return exit code.
+ */
+public interface TestExitCode {
+        public int getExitCode();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/TestUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test;
+
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collection;
+
+import nsk.share.Failure;
+import nsk.share.TestFailure;
+
+import static java.lang.String.format;
+
+public class TestUtils {
+    /**
+     * @throws nsk.share.Failure with given error message
+     *
+     */
+    public static void testFailed(Object errorMessage) {
+        throw new Failure(errorMessage.toString());
+    }
+
+    /**
+     * Checks that expr is true
+     *
+     * @throws nsk.share.Failure
+     *          when expr is false
+     */
+    public static void assertTrue(boolean expr, Object errorMessage) {
+        if (!expr)
+            testFailed(errorMessage);
+    }
+
+    /**
+     * Checks that obj is not null
+     *
+     * @throws nsk.share.Failure
+     *          when obj is null
+     */
+    public static void assertNotNull(Object obj, Object errorMessage) {
+        assertTrue(obj != null, errorMessage);
+    }
+
+    /**
+     * Checks that obj1 equal obj2
+     *
+     * @throws nsk.share.Failure
+     *          when obj1 is not equal obj2
+     */
+    public static void assertEquals(Object obj1, Object obj2, Object errorMessage) {
+        assertTrue(obj1.equals(obj2), new LazyFormatString("%s: [%s] != [%s]", errorMessage,  obj1, obj2));
+    }
+
+    public static <T> void assertNotInCollection(Collection<T> list, T value) {
+        assertTrue(! list.contains(value), new LazyFormatString("Internal error: %s is in collection %s", value, list));
+    }
+
+    public static <T> void assertInCollection(Collection<T> list, T value) {
+        assertTrue(list.contains(value), new LazyFormatString("Internal error: %s is not in collection %s", value, list));
+    }
+
+    public static void assertEquals(int i1, int i2) {
+        if (i1 != i2) {
+            throw new TestFailure(
+                    format("Check failed: %d != %d", i1, i2));
+        }
+    }
+
+    public static void fail(String msg) {
+        throw new TestFailure(msg);
+    }
+
+    public static void assertEquals(String s1, String s2) {
+        if (s1 == null && s2 == null) {
+            return;
+        }
+
+        if (s1 != null && s1.equals(s2)) {
+            return;
+        }
+
+        throw new TestFailure(format("Failed: %s != %s", s1, s2));
+    }
+
+    /**
+     * Check that obj is an instance of a class c.
+     *
+     * @param obj
+     * @param c
+     */
+    public static void assertExactClass(Object obj, Class c) {
+        if (obj.getClass() != c) {
+            throw new TestFailure(format("Exact class doesn't match: expected: %s; actual: %s",
+                                         c.getName(), obj.getClass().getName()));
+        }
+    }
+    /**
+     * @throws nsk.share.Failure (given exception is set as Failure cause)
+     *
+     */
+    public static void unexpctedException(Throwable exception) {
+        throw new Failure("Unexpected exception: " + exception, exception);
+    }
+
+    public static <T> T[] concatArrays(T[] a1, T[] a2) {
+        T[] result = Arrays.copyOf(a1, a1.length + a2.length);
+        System.arraycopy(a2, 0, result, a1.length, a2.length);
+        return result;
+    }
+
+    public static <T> T[] concatArrays(T[] a1, T[] a2, T[] a3) {
+        T[] result = Arrays.copyOf(a1, a1.length + a2.length + a3.length);
+        System.arraycopy(a2, 0, result, a1.length, a2.length);
+        System.arraycopy(a3, 0, result, a1.length + a2.length, a3.length);
+        return result;
+    }
+
+    public static <T> T[] concatArrays(T a1, T[] a2) {
+        @SuppressWarnings("unchecked")
+        T[] result = (T[]) Array.newInstance(a1.getClass(), 1 + a2.length);
+        result[0] = a1;
+        System.arraycopy(a2, 0, result, 1, a2.length);
+        return result;
+    }
+
+    public static <T> T[] cdr(T[] args) {
+        return Arrays.copyOfRange(args, 1, args.length);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/Tests.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package nsk.share.test;
+
+import nsk.share.log.*;
+import nsk.share.runner.*;
+import nsk.share.TestFailure;
+
+public class Tests {
+        protected static class TestRunner {
+                protected String[] args;
+                private Log log;
+                private MultiRunner runner;
+                private RunParams runParams;
+                private Test test;
+
+                public TestRunner(Test test, String[] args) {
+                        this.args = args;
+                        this.test = test;
+                }
+
+                public synchronized Log getLog() {
+                        if (log == null) {
+                                log = new LogSupport(System.out);
+                        }
+                        return log;
+                }
+
+                private synchronized RunParams getRunParams() {
+                        if (runParams == null) {
+                                runParams = RunParams.getInstance();
+                                runParams.parseCommandLine(args);
+                        }
+                        return runParams;
+                }
+
+                public void configure(Object o) {
+                        if (o instanceof LogAware)
+                                ((LogAware) o).setLog(getLog());
+                        if (o instanceof MultiRunnerAware)
+                                ((MultiRunnerAware) o).setRunner(getRunner());
+                        if (o instanceof RunParamsAware)
+                                ((RunParamsAware) o).setRunParams(getRunParams());
+                }
+
+                private synchronized MultiRunner getRunner() {
+                        if (runner == null) {
+                                runner = new ThreadsRunner();
+                                configure(runner);
+                        }
+                        return runner;
+                }
+
+
+                public void execute(Object o) {
+                        if (o instanceof Initializable)
+                                ((Initializable) o).initialize();
+                        int exitCode = 0;
+                        try {
+                                if (o instanceof Runnable)
+                                        ((Runnable) o).run();
+                                if (o instanceof TestExitCode)
+                                        exitCode = ((TestExitCode) o).getExitCode();
+                        } catch (RuntimeException t) {
+                                getLog().error(t);
+                                exitCode = 97;
+                        }
+                        if (exitCode != 95 && exitCode != 0)
+                                throw new TestFailure("Test exit code: " + exitCode);
+                        //System.exit(exitCode);
+                }
+
+                public void run() {
+                        configure(test);
+                        execute(test);
+                }
+        }
+
+
+        public static void runTest(Test test, String[] args) {
+                new TestRunner(test, args).run();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test.timeoutwatchdog;
+
+/**
+ * TimeoutHandler - interface to define reaction on timeout.
+ * @see TimeoutWatchdoc
+ */
+public interface TimeoutHandler {
+
+        /**
+         * Invoked when watchdog detects timeout. Subclasses must implement this method to define how timeout should be handled.
+         */
+        void handleTimeout();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/test/timeoutwatchdog/TimeoutWatchdog.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package nsk.share.test.timeoutwatchdog;
+
+import nsk.share.test.ExecutionController;
+
+/**
+ * This class watches for ExecutionControler and notifies TimeoutHander in case of timeout.
+ */
+public class TimeoutWatchdog implements Runnable {
+
+        private ExecutionController executionController;
+
+        private TimeoutHandler handler;
+
+        private static long CHECK_PERIOD = 1000; // In milliseconds
+
+        private TimeoutWatchdog(ExecutionController executionController, TimeoutHandler handler) {
+                this.executionController = executionController;
+                this.handler = handler;
+        }
+
+        /**
+         * Start watching for timeout.
+         * This method runs a new daemon thread that checks periodically if the observable test is still running.
+         * If timeout is detected <code>handler.handleTimeout()</code> will be called. If the test finishes normally the daemon
+         * thread will silently die.
+         * @param executionController - executionController used to monitor time left
+         * @param handler - handler on which handleTimeout() will be called
+         */
+        public static void watch(ExecutionController executionController, TimeoutHandler handler) {
+                Thread thread = new Thread(new TimeoutWatchdog(executionController, handler));
+                thread.setName("TimeoutWatchdog_thread");
+                thread.setDaemon(true);
+                thread.start();
+        }
+
+        @Override
+        public void run() {
+                try {
+                        while (true) {
+                                Thread.sleep(CHECK_PERIOD);
+                                if (!executionController.continueExecution()) {
+                                        System.out.println("Time expired. TimeoutWatchdog is calling TimeoutHandler.handleTimeout.");
+                                        handler.handleTimeout();
+                                }
+                        }
+                } catch (InterruptedException e) {
+                        throw new RuntimeException("Somebody dared to interrupt TimeoutWatchdog thread.");
+                }
+        }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/CommentedFileReader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.io.*;
+import java.util.LinkedList;
+
+/**
+ * Utility class intended to read file line by line and skip comments.
+ */
+public class CommentedFileReader {
+
+    /**
+     * Type of comments that should be removed from file.
+     */
+    public static enum CommentStyle {
+        /**
+         * Comments started with <i>#</i>.
+         */
+        BASH,
+        /**
+         * Comments started with <i>//</i>.
+         */
+        JAVA
+    }
+
+    /**
+     * Get lines from specified file and filter out comments.
+     * Only comments in BASH style will be filtered out.
+     *
+     * @param path to file that should be readed
+     * @return filtered lines from file
+     */
+    public static String[] readFile(String path) throws IOException {
+        return readFile(new File(path), CommentStyle.BASH);
+    }
+
+    /**
+     * Get lines from specified file and filter out comments.
+     * Only comments in BASH style will be filtered out.
+     *
+     * @param file that should be readed
+     * @return filtered lines from file
+     */
+    public static String[] readFile(File file) throws IOException {
+        return readFile(file, CommentStyle.BASH);
+    }
+
+    /**
+     * Get lines from specified file without comments.
+     *
+     * @param path to file that should be readed
+     * @param commentStyle describes what strings will be treated as comments
+     * @return filtered lines from file
+     */
+    public static String[] readFile(String path, CommentStyle commentStyle) throws IOException {
+        return readFile(new File(path), commentStyle);
+    }
+
+    /**
+     * Get lines from specified file without comments.
+     *
+     * @param file that should be readed
+     * @param commentStyle describes what strings will be treated as comments
+     * @return filtered lines from file
+     */
+    public static String[] readFile(File file, CommentStyle commentStyle) throws IOException {
+        LinkedList<String> entries = new LinkedList<String>();
+        BufferedReader reader = new BufferedReader(new FileReader(file));
+        String commentBeginning;
+
+        switch (commentStyle) {
+        case BASH:
+            commentBeginning = "#";
+            break;
+        case JAVA:
+            commentBeginning = "//";
+            break;
+        default:
+            throw new IllegalArgumentException("Unknown comment style");
+        }
+
+        while (true) {
+            String entry = reader.readLine();
+            if (entry == null) {
+                break;
+            }
+
+            entry = entry.replaceAll(commentBeginning + ".*", "").trim();
+
+            if (entry.length() > 0) {
+                entries.add(entry);
+            }
+        }
+
+        return entries.toArray(new String[entries.size()]);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/FileUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+
+public class FileUtils {
+
+    private static ClassLoader cl = ClassLoader.getSystemClassLoader();
+
+    public static byte[] readFile(File f) throws IOException {
+        FileInputStream is = new FileInputStream(f);
+        try {
+            return readStream(is);
+        } finally {
+            is.close();
+        }
+    }
+
+    public static byte[] readClass(String name) throws IOException {
+        return readResource(name.replace('.', '/') + ".class");
+    }
+
+    public static byte[] readResource(String name) throws IOException {
+        InputStream is = FileUtils.cl.getResourceAsStream(name);
+        if (is == null)
+            throw new IOException("Can't read resource " + name);
+
+        try {
+            return readStream(is);
+        } finally {
+            is.close();
+        }
+    }
+
+    public static byte[] readStream(InputStream is) throws IOException {
+        byte buf[] = new byte[0xFFFF];
+        int offset = 0;
+        int r;
+        while ((r = is.read(buf, offset, buf.length - offset)) > 0)
+            offset += r;
+        return Arrays.copyOf(buf, offset);
+    }
+
+    public static void writeBytesToFile(File file, byte[] buf)
+            throws IOException {
+        FileOutputStream fos = new FileOutputStream(file);
+        try {
+            fos.write(buf);
+        } finally {
+            fos.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/InMemoryJavaCompiler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+import java.io.ByteArrayOutputStream;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+
+
+public class InMemoryJavaCompiler {
+
+    public static Map<String, byte[]> compile(Map<String, ? extends CharSequence> inputMap) {
+        Collection<JavaFileObject> sourceFiles = new LinkedList<JavaFileObject>();
+        for (Entry<String, ? extends CharSequence> entry : inputMap.entrySet()) {
+            sourceFiles.add(new SourceFile(entry.getKey(), entry.getValue()));
+        }
+
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        FileManager fileManager = new FileManager(compiler.getStandardFileManager(null, null, null));
+
+        Writer writer = new StringWriter();
+        Boolean exitCode = compiler.getTask(writer, fileManager, null, null, null, sourceFiles).call();
+        if (!exitCode) {
+            System.out.println("*********** javac output begin ***********");
+            System.out.println(writer.toString());
+            System.out.println("*********** javac output end ***********");
+            if (writer.toString().contains("java.lang.OutOfMemoryError")) {
+                System.out.println("Got OOME while performing in memory compilation. It happens on weak hosts and there is nothing we can do. ");
+                throw new OutOfMemoryError("Got OOME while performing in memory compilation.");
+            }
+            throw new RuntimeException("Test bug: in memory compilation failed.");
+        }
+        return fileManager.getByteCode();
+    }
+
+    // Wraper for class file
+    static class ClassFile extends SimpleJavaFileObject {
+
+        private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        protected ClassFile(String name) {
+            super(URI.create("memo:///" + name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS);
+        }
+
+        @Override
+        public ByteArrayOutputStream openOutputStream() { return this.baos; }
+
+        byte[] toByteArray() { return baos.toByteArray(); }
+    }
+
+    // File manager which spawns ClassFile instances by demand
+    static class FileManager extends ForwardingJavaFileManager<JavaFileManager> {
+
+        private Map<String, ClassFile> classesMap = new HashMap<String, ClassFile>();
+
+        protected FileManager(JavaFileManager fileManager) {
+            super(fileManager);
+        }
+
+        @Override
+        public ClassFile getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject source) {
+            ClassFile classFile = new ClassFile(name);
+            classesMap.put(name, classFile);
+            return classFile;
+        }
+
+        public Map<String, byte[]> getByteCode() {
+            Map<String, byte[]> result = new HashMap<String, byte[]>();
+            for (Entry<String, ClassFile> entry : classesMap.entrySet()) {
+                result.put(entry.getKey(), entry.getValue().toByteArray());
+            }
+            return result;
+        }
+    }
+
+    // Wrapper for source file
+    static class SourceFile extends SimpleJavaFileObject {
+
+        private CharSequence sourceCode;
+
+        public SourceFile(String name, CharSequence sourceCode) {
+            super(URI.create("memo:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
+            this.sourceCode = sourceCode;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignore) {
+            return this.sourceCode;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include "jni.h"
+#include "native_thread.h"
+#ifdef _WIN32
+#include <windows.h>
+#include <process.h>
+#include <vdmdbg.h>
+#include <dbghelp.h>
+#else /* _WIN32 */
+#include <unistd.h>
+#include <signal.h>
+#endif /* _WIN32 */
+#include "jni_tools.h"
+
+/*
+ * Class:     vm_share_ProcessUtils
+ * Method:    sendSignal
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_vm_share_ProcessUtils_sendSignal
+(JNIEnv *env, jclass class, jint signalNum) {
+#ifdef _WIN32
+/* TODO TODO TODO
+        int dw;
+        LPVOID lpMsgBuf;
+        if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0)) {
+                dw = GetLastError();
+                FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                                NULL,
+                                dw,
+                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                                (LPTSTR) &lpMsgBuf,
+                                0,
+                                NULL
+                             );
+                printf("%s\n", (LPTSTR)lpMsgBuf);
+                LocalFree(lpMsgBuf);
+                return JNI_FALSE;
+        }
+        */
+        return JNI_TRUE;
+#else /* _WIN32 */
+        if (kill(getpid(), signalNum) < 0)
+                return JNI_FALSE;
+        return JNI_TRUE;
+#endif /* _WIN32 */
+}
+
+/*
+ * Class:     vm_share_ProcessUtils
+ * Method:    sendCtrlBreak
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_vm_share_ProcessUtils_sendCtrlBreak
+(JNIEnv *env, jclass class) {
+#ifdef _WIN32
+        int dw;
+        LPVOID lpMsgBuf;
+        if (!GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0)) {
+                dw = GetLastError();
+                FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                                NULL,
+                                dw,
+                                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                                (LPTSTR) &lpMsgBuf,
+                                0,
+                                NULL
+                             );
+                printf("%s\n", (LPTSTR)lpMsgBuf);
+                LocalFree(lpMsgBuf);
+                return JNI_FALSE;
+        }
+        return JNI_TRUE;
+#else /* _WIN32 */
+        if (kill(getpid(), SIGQUIT) < 0)
+                return JNI_FALSE;
+        return JNI_TRUE;
+#endif /* _WIN32 */
+}
+
+#ifdef _WIN32
+static BOOL  (WINAPI *_MiniDumpWriteDump)  ( HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION,
+                                            PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION);
+void reportLastError(const char *msg) {
+        long errcode = GetLastError();
+        if (errcode != 0) {
+                DWORD len = 0;
+                char *buf;
+                size_t n = (size_t)FormatMessage(
+                                FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER,
+                                NULL,
+                                errcode,
+                                0,
+                                (LPSTR) &buf,
+                                (DWORD)len,
+                                NULL);
+                if (n > 3) {
+                        /* Drop final '.', CR, LF */
+                        if (buf[n - 1] == '\n') n--;
+                        if (buf[n - 1] == '\r') n--;
+                        if (buf[n - 1] == '.') n--;
+                        buf[n] = '\0';
+                }
+                printf("%s: %s\n", msg, buf);
+                LocalFree(buf);
+        }
+}
+
+#endif /* _WIN32 */
+
+jboolean doDumpCore() {
+#ifdef _WIN32
+        char path[MAX_PATH];
+        DWORD size;
+        DWORD pathLen = (DWORD) sizeof(path);
+        HINSTANCE dbghelp;
+        MINIDUMP_EXCEPTION_INFORMATION* pmei;
+
+        HANDLE hProcess = GetCurrentProcess();
+        DWORD processId = GetCurrentProcessId();
+        HANDLE dumpFile;
+        MINIDUMP_TYPE dumpType;
+        static const char* cwd;
+        static const char* name = "DBGHELP.DLL";
+
+        printf("# TEST: creating Windows minidump...\n");
+        if ((size = GetSystemDirectory(path, pathLen)) > 0) {
+                strcat(path, "\\");
+                strcat(path, name);
+                dbghelp = LoadLibrary(path);
+                if (dbghelp == NULL)
+                        reportLastError("Load DBGHELP.DLL from system directory");
+        } else {
+                printf("GetSystemDirectory returned 0\n");
+        }
+
+        // try Windows directory
+        if (dbghelp == NULL && ((size = GetWindowsDirectory(path, pathLen)) > 6)) {
+                strcat(path, "\\");
+                strcat(path, name);
+                dbghelp = LoadLibrary(path);
+                if (dbghelp == NULL) {
+                        reportLastError("Load DBGHELP.DLL from Windows directory");
+                }
+        }
+        if (dbghelp == NULL) {
+                printf("Failed to load DBGHELP.DLL\n");
+                return JNI_FALSE;
+        }
+
+        _MiniDumpWriteDump = (
+                        BOOL(WINAPI *)( HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_EXCEPTION_INFORMATION,
+                                PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION)) GetProcAddress(dbghelp, "MiniDumpWriteDump");
+
+        if (_MiniDumpWriteDump == NULL) {
+                printf("Failed to find MiniDumpWriteDump() in module dbghelp.dll");
+                return JNI_FALSE;
+        }
+        dumpType = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithHandleData);
+
+        // Older versions of dbghelp.h doesn't contain all the dumptypes we want, dbghelp.h with
+        // API_VERSION_NUMBER 11 or higher contains the ones we want though
+#if API_VERSION_NUMBER >= 11
+        dumpType = (MINIDUMP_TYPE)(dumpType | MiniDumpWithFullMemoryInfo | MiniDumpWithThreadInfo |
+                        MiniDumpWithUnloadedModules);
+#endif
+
+        dumpFile = CreateFile("core.mdmp", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+        if (dumpFile == INVALID_HANDLE_VALUE) {
+                reportLastError("Failed to create file for dumping");
+                return JNI_FALSE;
+        }
+        pmei = NULL;
+
+
+        // Older versions of dbghelp.dll (the one shipped with Win2003 for example) may not support all
+        // the dump types we really want. If first call fails, lets fall back to just use MiniDumpWithFullMemory then.
+        if (_MiniDumpWriteDump(hProcess, processId, dumpFile, dumpType, pmei, NULL, NULL) == FALSE &&
+                        _MiniDumpWriteDump(hProcess, processId, dumpFile, (MINIDUMP_TYPE)MiniDumpWithFullMemory, pmei, NULL, NULL) == FALSE) {
+                reportLastError("Call to MiniDumpWriteDump() failed");
+                return JNI_FALSE;
+        }
+
+        CloseHandle(dumpFile);
+        printf("# TEST: minidump created\n");
+        // Emulate Unix behaviour - exit process.
+        ExitProcess(137);
+
+        return JNI_TRUE;
+#else /* _WIN32 */
+        if (kill(getpid(), SIGSEGV) < 0)
+                return JNI_FALSE;
+        return JNI_TRUE;
+#endif /* _WIN32 */
+
+}
+
+/*
+ * Class:     vm_share_ProcessUtils
+ * Method:    dumpCore
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_vm_share_ProcessUtils_dumpCore
+  (JNIEnv *env, jclass class)
+{
+        return doDumpCore();
+}
+
+/*
+ * Class:     vm_share_ProcessUtils
+ * Method:    getPid
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_vm_share_ProcessUtils_getPid
+  (JNIEnv *env, jclass class) {
+#ifdef _WIN32
+        return _getpid();
+#else /* _WIN32 */
+        return getpid();
+#endif /* _WIN32 */
+}
+
+
+/*
+ * Class:     vm_share_ProcessUtils
+ * Method:    getPid
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_vm_share_ProcessUtils_getWindowsPid
+  (JNIEnv *env, jclass class, jlong handle) {
+#ifdef _WIN32
+        return GetProcessId((HANDLE) handle);
+#else /* _WIN32 */
+        return -1;
+#endif /* _WIN32 */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/ProcessUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.Field;
+
+import nsk.share.TestBug;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+
+public final class ProcessUtils {
+    static {
+        System.loadLibrary("ProcessUtils");
+    }
+
+    private ProcessUtils() {}
+
+    /**
+     * Send Ctrl-\ to java process and Ctrl-Break on Windows.
+     * This will usually trigger stack dump for all threads and
+     * may trigger heap dump.
+     *
+     * @return true if it was successful
+     */
+    public static native boolean sendCtrlBreak();
+
+    /**
+     * Send any signal to java process on Unix. It currently does nothing on Windows.
+     *
+     * @return true if it was successful
+     */
+    public static native boolean sendSignal(int signalNum);
+
+    /**
+     * Force java process to dump core.
+     *
+     * This is done by sending SIGSEGV on unix systems.
+     *
+     * @return true if it was successful, false if not (for example on Windows)
+     */
+    public static native boolean dumpCore();
+
+    /**
+     * Get PID of java process.
+     *
+     * @return PID
+     */
+    public static native int getPid();
+
+    public static int getPid(Process process) {
+        Throwable exception;
+        try {
+            Field pidField = process.getClass().getDeclaredField("pid");
+            pidField.setAccessible(true);
+            return ((Integer) pidField.get(process)).intValue();
+        } catch (NoSuchFieldException e) {
+            exception = e;
+        } catch (IllegalAccessException e) {
+            exception = e;
+        }
+        // Try to get Windows handle
+        try {
+            Field handleField = process.getClass().getDeclaredField("handle");
+            handleField.setAccessible(true);
+            long handle = ((Long) handleField.get(process)).longValue();
+            return getWindowsPid(handle);
+        } catch (NoSuchFieldException e) {
+            exception = e;
+        } catch (IllegalAccessException e) {
+            exception = e;
+        }
+        throw new TestBug("Unable to determine pid from process class " + process.getClass(), exception);
+    }
+
+    private static native int getWindowsPid(long handle);
+
+    @SuppressWarnings("restriction")
+    public static void dumpHeapWithHotspotDiagnosticMXBean(String fileName) throws IOException {
+        System.err.println("Dumping heap to " + fileName);
+
+        File f = new File(fileName);
+        if (f.exists())
+            f.delete();
+
+        HotSpotDiagnosticMXBean b = ManagementFactory.getPlatformMXBeans(
+                com.sun.management.HotSpotDiagnosticMXBean.class).get(0);
+        b.dumpHeap(fileName, false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/RandomEx.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+public class RandomEx extends Random {
+    private final Map<Class<?>, Supplier<?>> map = new HashMap<>();
+
+    {
+        map.put(Boolean.class, this::nextBoolean);
+        map.put(boolean.class, this::nextBoolean);
+        map.put(Byte.class, this::nextByte);
+        map.put(byte.class, this::nextByte);
+        map.put(Short.class, this::nextShort);
+        map.put(short.class, this::nextShort);
+        map.put(Character.class, this::nextChar);
+        map.put(char.class, this::nextChar);
+        map.put(Integer.class, this::nextInt);
+        map.put(int.class, this::nextInt);
+        map.put(Long.class, this::nextLong);
+        map.put(long.class, this::nextLong);
+        map.put(Float.class, this::nextFloat);
+        map.put(float.class, this::nextFloat);
+        map.put(Double.class, this::nextDouble);
+        map.put(double.class, this::nextDouble);
+    }
+
+    public RandomEx() {
+    }
+
+    public RandomEx(long seed) {
+        super(seed);
+    }
+
+    public byte nextByte() {
+        return (byte) next(Byte.SIZE);
+    }
+
+    public short nextShort() {
+        return (short) next(Short.SIZE);
+    }
+
+    public char nextChar() {
+        return (char) next(Character.SIZE);
+    }
+
+    public <T> T next(Predicate<T> p, T dummy) {
+        T result;
+        do {
+            result = next(dummy);
+        } while (!p.test(result));
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T next(T dummy) {
+        Supplier<?> supplier = map.get(dummy.getClass());
+        if (supplier == null) {
+            throw new IllegalArgumentException("supplier for <" +
+                    dummy.getClass() + ">is not found");
+        }
+        return (T) supplier.get();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/StringUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+import java.util.function.Predicate;
+
+public class StringUtils {
+
+    public static byte[] binaryReplace(final byte[] src, String search,
+            String replacement) {
+        if (search.length() == 0)
+            return src;
+
+        int nReplaced = 0;
+
+        try {
+            final byte[] bSrch = search.getBytes("ASCII");
+            final byte[] bRepl = replacement.getBytes("ASCII");
+
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            try {
+                searching: for (int i = 0; i < src.length; i++) {
+                    if (src[i] == bSrch[0]) {
+                        replacing: do {
+                            for (int ii = 1; ii < Math.min(bSrch.length,
+                                    src.length - i); ii++)
+                                if (src[i + ii] != bSrch[ii])
+                                    break replacing;
+
+                            out.write(bRepl);
+                            i += bSrch.length - 1;
+                            nReplaced++;
+                            continue searching;
+                        } while (false);
+                    }
+
+                    out.write(src[i]);
+                }
+
+            return out.toByteArray();
+
+            } finally {
+                out.close();
+            }
+        } catch (Exception e) {
+            RuntimeException t = new RuntimeException("Test internal error");
+            t.initCause(e);
+            throw t;
+        }
+    }
+
+    public static String generateString(Random rng, int length,
+            Predicate<Character> predicate) {
+        if (length <= 0) {
+            throw new IllegalArgumentException("length <= 0");
+        }
+        StringBuilder builder = new StringBuilder(length);
+        for (int i = 0; i < length; ++i) {
+            char tmp;
+            do {
+                tmp = (char) rng.nextInt(Character.MAX_VALUE);
+            } while (!predicate.test(tmp));
+            builder.append(tmp);
+        }
+        return builder.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/UnsafeAccess.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import java.lang.reflect.Field;
+
+import jdk.internal.misc.Unsafe;
+
+@SuppressWarnings("restriction")
+public class UnsafeAccess {
+    public static Unsafe unsafe;
+
+    static {
+        try {
+            unsafe = Unsafe.getUnsafe();
+        } catch ( Exception e ) {
+            e.printStackTrace();
+        }
+    }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/VMRuntimeEnvUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+
+import java.lang.management.ManagementFactory;
+import java.util.Objects;
+
+public class VMRuntimeEnvUtils {
+    private static HotSpotDiagnosticMXBean DIAGNOSTIC_BEAN
+            = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+
+    private VMRuntimeEnvUtils() {
+    }
+
+    public static boolean isJITEnabled() {
+        boolean isJITEnabled = ManagementFactory.getCompilationMXBean() != null;
+
+        return isJITEnabled;
+    }
+
+    /**
+     * Returns value of VM option.
+     *
+     * @param name option's name
+     * @return value of option or {@code null}, if option doesn't exist
+     * @throws NullPointerException if name is null
+     * @see HotSpotDiagnosticMXBean#getVMOption(String)
+     */
+    public static String getVMOption(String name) {
+        Objects.requireNonNull(name);
+        VMOption tmp;
+        try {
+            tmp = DIAGNOSTIC_BEAN.getVMOption(name);
+        } catch (IllegalArgumentException e) {
+            tmp = null;
+        }
+        return (tmp == null ? null : tmp.getValue());
+    }
+
+    /**
+     * Returns value of VM option or default value.
+     *
+     * @param name         option's name
+     * @param defaultValue default value
+     * @return value of option or {@code defaultValue}, if option doesn't exist
+     * @throws NullPointerException if name is null
+     * @see #getVMOption(String)
+     */
+    public static String getVMOption(String name, String defaultValue) {
+        String result = getVMOption(name);
+        return result == null ? defaultValue : result;
+    }
+
+    /**
+     * Returns if a boolean VM option is enabled or not.
+     *
+     * @param name  option's name
+     * @return true iff enabled
+     * @throws IllegalArgumentException if naming non-boolean or non-existing option
+     */
+    public static boolean isVMOptionEnabled(String name) {
+        String isSet = getVMOption(name, "error");
+        if (isSet.equals("true")) {
+            return true;
+        } else if (isSet.equals("false")) {
+            return false;
+        }
+        throw new IllegalArgumentException(name + " is not a boolean option.");
+    }
+
+    /**
+     * Sets a specified value for VM option of given name.
+     *
+     * @param name  option's name
+     * @param value new value
+     * @throws NullPointerException     if name is null
+     * @throws IllegalArgumentException if new value is invalid or if vm option
+     *                                  is not writable.
+     * @see HotSpotDiagnosticMXBean#setVMOption(String, String)
+     */
+    public static void setVMOption(String name, String value) {
+        Objects.requireNonNull(name);
+        DIAGNOSTIC_BEAN.setVMOption(name, value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingHeap.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.gc;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import nsk.share.TestFailure;
+import nsk.share.test.ExecutionController;
+
+public class TriggerUnloadingByFillingHeap implements TriggerUnloadingHelper {
+
+    public void triggerUnloading(ExecutionController stresser) {
+        List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
+        if (jvmArgs.contains("-XX:+ExplicitGCInvokesConcurrent")) {
+                throw new TestFailure("Test bug! Found -XX:+ExplicitGCInvokesConcurrent in jvm args. TriggerUnloadingByFillingHeap.triggerUnloading will not work!.");
+        }
+
+        System.out.println("collections invoked: " + provokeGC(stresser));
+        System.out.println("collections invoked: " + provokeGC(stresser));
+        System.out.println("collections invoked: " + provokeGC(stresser));
+    }
+
+    private static long getGCCounter() {
+        return ManagementFactory.getGarbageCollectorMXBeans().get(1).getCollectionCount();
+    }
+
+    private static Random random = new Random();
+
+    public static byte[] garbage; //make it reference public to avoid compiler optimizations
+
+    private static long provokeGC(ExecutionController stresser) {
+        long initCounter = getGCCounter();
+        ArrayList<byte[]> list = new ArrayList<byte[]>();
+        while (getGCCounter() == initCounter && stresser.continueExecution()) {
+            list.add(new byte[1024]);
+
+            garbage = new byte[1024];
+            if (random.nextInt(10) % 10 < 3 && !list.isEmpty()) {
+                list.remove(0);
+            }
+            System.gc();
+        }
+        return getGCCounter() - initCounter;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingByFillingMetaspace.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.gc;
+
+import java.util.ArrayList;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import metaspace.stressHierarchy.common.exceptions.GotWrongOOMEException;
+import nsk.share.gc.gp.classload.GeneratedClassProducer;
+import nsk.share.test.ExecutionController;
+
+public class TriggerUnloadingByFillingMetaspace implements
+        TriggerUnloadingHelper {
+
+    private static final int NUMBER_OF_THREADS = 30;
+
+    private static class FillMetaspace {
+        private volatile boolean gotOOME = false;
+        private ExecutionController stresser;
+        private GeneratedClassProducer generatedClassProducer = new GeneratedClassProducer("metaspace.stressHierarchy.common.HumongousClass");
+
+        public FillMetaspace(ExecutionController stresser) { this.stresser = stresser; }
+
+        private class FillMetaspaceTask implements Callable<Object> {
+            @Override
+            public Object call() throws Exception {
+                while (stresser.continueExecution() && ! gotOOME) {
+                    try {
+                        generatedClassProducer.create(-100500); //argument is not used.
+                    } catch (OutOfMemoryError oome) {
+                        if (!isInMetaspace(oome)) {
+                            throw new GotWrongOOMEException("Got OOME in heap while gaining OOME in metaspace. Test result can't be valid.");
+                        }
+                        gotOOME = true;
+                    }
+                }
+                return null;
+            }
+        }
+    }
+
+    private static boolean isInMetaspace(OutOfMemoryError error) {
+        return error.getMessage().trim().toLowerCase().contains("metadata");
+    }
+
+    @Override
+    public void triggerUnloading(ExecutionController stresser) {
+        try {
+            FillMetaspace fillMetaspace = new FillMetaspace(stresser);
+            ArrayList<Callable<Object>> tasks = new ArrayList<Callable<Object>>(NUMBER_OF_THREADS);
+            for (int i = 0; i < NUMBER_OF_THREADS; i++) {
+                tasks.add(fillMetaspace.new FillMetaspaceTask());
+            }
+            ExecutorService executorService = Executors.newCachedThreadPool();
+            try {
+                executorService.invokeAll(tasks);
+            } catch (InterruptedException e) {
+                System.out.println("Process of gaining OOME in metaspace was interrupted.");
+                e.printStackTrace();
+            }
+        } catch (OutOfMemoryError e) {
+            if (!isInMetaspace(e)) {
+                throw new GotWrongOOMEException("Got OOME in heap while gaining OOME in metaspace. Test result can't be valid.");
+            }
+            return;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingHelper.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.gc;
+
+import nsk.share.test.ExecutionController;
+
+public interface TriggerUnloadingHelper {
+
+    public void triggerUnloading(ExecutionController stresser);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/gc/TriggerUnloadingWithWhiteBox.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.gc;
+
+
+import sun.hotspot.WhiteBox;
+import nsk.share.test.ExecutionController;
+
+public class TriggerUnloadingWithWhiteBox implements TriggerUnloadingHelper {
+
+        private final static WhiteBox wb = WhiteBox.getWhiteBox();
+
+        @Override
+        public void triggerUnloading(ExecutionController stresser) {
+                wb.fullGC();
+        }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/libProcessUtils.c	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "jni_tools.c"
+#include "nsk_tools.c"
+#include "ProcessUtils.c"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/MemoryPoolFinder.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.monitoring;
+
+import java.lang.management.*;
+
+public enum MemoryPoolFinder {
+    CODE_CACHE,
+        EDEN_SPACE,
+        SURVIVOR_SPACE,
+        OLD_GEN,
+        PERM_GEN,
+        METASPACE,
+        CLASS_METASPACE;
+
+    public static MemoryPoolMXBean findPool(MemoryPoolFinder pool) {
+        for(MemoryPoolMXBean candidate : ManagementFactory.getMemoryPoolMXBeans()) {
+            boolean found = false;
+            switch(pool) {
+            case CODE_CACHE:
+                found = candidate.getName().contains("Code Cache");
+                break;
+            case EDEN_SPACE:
+                found = candidate.getName().contains("Eden");
+                break;
+            case SURVIVOR_SPACE:
+                found = candidate.getName().contains("Survivor");
+                break;
+            case OLD_GEN:
+                found = candidate.getName().contains("Old") || candidate.getName().contains("Tenured");
+                break;
+            case PERM_GEN:
+                found = candidate.getName().contains("Perm");
+                break;
+            case METASPACE:
+                found = candidate.getName().contains("Metaspace") && !candidate.getName().contains("Class Metaspace");
+                break;
+            case CLASS_METASPACE:
+                found = candidate.getName().contains("Class Metaspace");
+                break;
+            }
+            if (found) return candidate;
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryManagerData.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.monitoring.data;
+
+import java.lang.management.*;
+import javax.management.*;
+import java.io.Serializable;
+
+public class MemoryManagerData implements MemoryManagerMXBean, Serializable {
+        private String[] memoryPoolNames;
+        private String name;
+        private boolean valid;
+
+        public MemoryManagerData(String[] memoryPoolNames, String name, boolean valid) {
+                this.memoryPoolNames = memoryPoolNames;
+                this.name = name;
+                this.valid = valid;
+        }
+
+        public MemoryManagerData(MemoryManagerMXBean memoryManager) {
+                this.memoryPoolNames = memoryManager.getMemoryPoolNames();
+                this.name = memoryManager.getName();
+                this.valid = memoryManager.isValid();
+        }
+
+        public String[] getMemoryPoolNames() {
+                return memoryPoolNames;
+        }
+
+        public String getName() {
+                return name;
+        }
+
+        public boolean isValid() {
+                return valid;
+        }
+
+    public ObjectName getObjectName() {
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryPoolData.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.monitoring.data;
+
+import java.lang.management.MemoryPoolMXBean;
+import java.io.Serializable;
+
+public class MemoryPoolData implements Serializable {
+        private String name;
+        private boolean valid;
+        private MemoryUsageData usage;
+
+        public MemoryPoolData(String name, boolean valid, MemoryUsageData usage) {
+                this.name = name;
+                this.valid = valid;
+        }
+
+        public MemoryPoolData(MemoryPoolMXBean memoryManager) {
+                this.name = memoryManager.getName();
+                this.valid = memoryManager.isValid();
+                this.usage = new MemoryUsageData(memoryManager.getUsage());
+        }
+
+        public String getName() {
+                return name;
+        }
+
+        public boolean hasName(String name) {
+                return this.name.equals(name);
+        }
+
+        public boolean isValid() {
+                return valid;
+        }
+
+        public MemoryUsageData getUsage() {
+                return usage;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/monitoring/data/MemoryUsageData.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.monitoring.data;
+
+import java.io.Serializable;
+import java.lang.management.MemoryUsage;
+import nsk.share.log.Log;
+
+public class MemoryUsageData implements Serializable {
+        private long init;
+        private long used;
+        private long committed;
+        private long max;
+
+        public MemoryUsageData(long init, long used, long committed, long max) {
+                this.init = init;
+                this.used = used;
+                this.committed = committed;
+                this.max = max;
+        }
+
+        public MemoryUsageData(MemoryUsage usage) {
+                this.init = usage.getInit();
+                this.used = usage.getUsed();
+                this.committed = usage.getCommitted();
+                this.max = usage.getMax();
+        }
+
+        public MemoryUsageData(MemoryUsageData usage, MemoryUsageData usage1) {
+                this.init = usage.getInit() + usage1.getInit();
+                this.used = usage.getUsed() + usage1.getUsed();
+                this.committed = usage.getCommitted() + usage1.getCommitted();
+                this.max = usage.getMax() + usage1.getMax();
+        }
+
+        public long getInit() {
+                return init;
+        }
+
+        public long getUsed() {
+                return used;
+        }
+
+        public long getMax() {
+                return max;
+        }
+
+        public long getFree() {
+                return committed - used;
+        }
+
+        public long getCommitted() {
+                return committed;
+        }
+
+        public void log(Log log) {
+                log.info("    Init: " + init);
+                log.info("    Used: " + used);
+                log.info("    Committed: " + committed);
+                log.info("    Max: " + max);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/BasicObjectFactory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options;
+
+import java.util.HashMap;
+import java.util.Map;
+import nsk.share.TestBug;
+
+/**
+ * This class allows user to create an {@link ObjectFactory} implementation
+ * via @{@link vm.share.options.Factory} annotation. See the source code of
+ * {@link vm.share.options.test.BasicObjectFactoryUsageExample} and
+ * {@link vm.share.options.test.ExampleWithNonprimitiveOptions}.
+ * @see Factory
+ * @see FClass
+ * @see ObjectFactory
+ */
+public class BasicObjectFactory<T> implements ObjectFactory<T>
+{
+    public String getPlaceholder()
+    {
+        return getAnnotaion().placeholder_text();
+    }
+
+    public String[] getPossibleValues()
+    {
+        return getTypesMap().keySet().toArray(new String[0]);
+    }
+
+    public String getDescription()
+    {
+        return getAnnotaion().description().equals(Factory.defDescription)? null : getAnnotaion().description();
+    }
+
+    public String getDefaultValue()
+    {
+        return getAnnotaion().default_value().equals(Factory.defDefaultValue)? null :
+                getAnnotaion().default_value();
+    }
+
+    public String getParameterDescription(String key)
+    {
+        return getTypesMap().get(key).description();
+    }
+
+
+    // shouldn't value be named key?
+
+    public T getObject(String value)
+    {
+        try
+        {
+            @SuppressWarnings(value="unchecked")
+            T result = (T) getTypesMap().get(value).type().newInstance();
+            return result;
+        } catch (InstantiationException ex)
+        {
+            throw new TestBug("Error while trying to instantiate via " + this.getClass() + " for key " + value, ex);
+        } catch (IllegalAccessException ex)
+        {
+            throw new TestBug("Error while trying to instantiate via " + this.getClass() + " for key " + value, ex);
+        }
+    }
+
+    protected Factory getAnnotaion()
+    {
+        if(!this.getClass().isAnnotationPresent(Factory.class))
+            throw new TestBug(" Found an unnotated BasicObjectFactory subclass.");
+        Factory factoryAnn = this.getClass().getAnnotation(Factory.class);
+        return factoryAnn;
+    }
+
+    protected Map<String, FClass> getTypesMap()
+    {   // probably there could be some lazy initialization, but I decided not to deal with that.
+        FClass[] types = getAnnotaion().classlist();
+        Map<String, FClass> typesMap = new HashMap<String, FClass>(types.length);
+        for (FClass type : types)
+        {
+            typesMap.put(type.key(), type);
+        }
+        return typesMap;
+
+    }
+
+    // see ExampleWithNonprimitiveOptions instead.
+//    public void test()
+//    {
+//        if(!this.getClass().isAnnotationPresent(Factory.class))
+//            throw new RuntimeException(" Found an unnotated BasicObjectFactory subclass.");
+//        Factory factoryAnn = this.getClass().getAnnotation(Factory.class);
+//        System.out.println(" placeholder_text " + factoryAnn.placeholder_text());
+//        System.out.println(" default_value  " +
+//                (factoryAnn.default_value().equals(Factory.defDefault_value) ? null : factoryAnn.default_value()) );
+//
+//    }
+//
+//    @Factory(placeholder_text="number", default_value="test",
+//    classlist = {
+//    @FClass( key="int", description="integer", type=int.class),
+//    @FClass( key="boolean", description="boolean", type=boolean.class)
+//    } )
+//    public static class testOF extends BasicObjectFactory<BasicObjectFactory> {}
+//
+////    @Factory(placeholder_text="placehldr1")
+////    public static class testOF1 extends BasicObjectFactory<BasicObjectFactory> {}
+//
+//
+//    public static void main(String[] args)
+//    {
+//        BasicObjectFactory bof = new testOF();
+//        bof.test();
+////        new testOF1().test();
+//
+//    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/BasicOptionObjectFactory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options;
+
+import java.util.HashMap;
+import java.util.Map;
+import nsk.share.TestBug;
+
+/**
+ * This class allows user to create an {@link ObjectFactory} implementation
+ * via @{@link vm.share.options.Factory} annotation. See the source code of
+ * {@link vm.share.options.test.BasicObjectFactoryUsageExample} and
+ * {@link vm.share.options.test.ExampleWithNonprimitiveOptions}.
+ * @see Factory
+ * @see FClass
+ * @see ObjectFactory
+ */
+public class BasicOptionObjectFactory<T> implements OptionObjectFactory<T>
+{
+    public String getPlaceholder()
+    {
+        return getAnnotaion().placeholder_text();
+    }
+
+    public String[] getPossibleValues()
+    {
+        return getTypesMap().keySet().toArray(new String[0]);
+    }
+
+    public String getDescription()
+    {
+        return getAnnotaion().description().equals(Factory.defDescription)? null : getAnnotaion().description();
+    }
+
+    public String getDefaultValue()
+    {
+        return getAnnotaion().default_value().equals(Factory.defDefaultValue)? null :
+                getAnnotaion().default_value();
+    }
+
+    public String getParameterDescription(String key)
+    {
+        return getTypesMap().get(key).description();
+    }
+
+
+    // shouldn't value be named key?
+
+    public T getObject(String value)
+    {
+        try
+        {
+            @SuppressWarnings(value="unchecked")
+            T result = (T) getTypesMap().get(value).type().newInstance();
+            return result;
+        } catch (InstantiationException ex)
+        {
+            throw new TestBug("Error while trying to instantiate via " + this.getClass() + " for key " + value, ex);
+        } catch (IllegalAccessException ex)
+        {
+            throw new TestBug("Error while trying to instantiate via " + this.getClass() + " for key " + value, ex);
+        }
+    }
+
+    protected Factory getAnnotaion()
+    {
+        if(!this.getClass().isAnnotationPresent(Factory.class))
+            throw new TestBug(" Found an unnotated BasicObjectFactory subclass.");
+        Factory factoryAnn = this.getClass().getAnnotation(Factory.class);
+        return factoryAnn;
+    }
+
+    protected Map<String, FClass> getTypesMap()
+    {   // probably there could be some lazy initialization, but I decided not to deal with that.
+        FClass[] types = getAnnotaion().classlist();
+        Map<String, FClass> typesMap = new HashMap<String, FClass>(types.length);
+        for (FClass type : types)
+        {
+            typesMap.put(type.key(), type);
+        }
+        return typesMap;
+
+    }
+
+    // see ExampleWithNonprimitiveOptions instead.
+//    public void test()
+//    {
+//        if(!this.getClass().isAnnotationPresent(Factory.class))
+//            throw new RuntimeException(" Found an unnotated BasicObjectFactory subclass.");
+//        Factory factoryAnn = this.getClass().getAnnotation(Factory.class);
+//        System.out.println(" placeholder_text " + factoryAnn.placeholder_text());
+//        System.out.println(" default_value  " +
+//                (factoryAnn.default_value().equals(Factory.def_default_value) ? null : factoryAnn.default_value()) );
+//
+//    }
+//
+//    @Factory(placeholder_text="number", default_value="test",
+//    classlist = {
+//    @FClass( key="int", description="integer", type=int.class),
+//    @FClass( key="boolean", description="boolean", type=boolean.class)
+//    } )
+//    public static class testOF extends BasicObjectFactory<BasicObjectFactory> {}
+//
+////    @Factory(placeholder_text="placehldr1")
+////    public static class testOF1 extends BasicObjectFactory<BasicObjectFactory> {}
+//
+//
+//    public static void main(String[] args)
+//    {
+//        BasicObjectFactory bof = new testOF();
+//        bof.test();
+////        new testOF1().test();
+//
+//    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/FClass.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+import java.lang.annotation.*;
+/**
+ * This is an auxilary declaration for use with @Factory annotation,
+ * allows to add a particular class to the factory.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface FClass
+{
+//    final public static String def_default_value = "[no default]";
+    /**
+     * A key which tells the BasicObjectFactory to instaniate given class,
+     * is mandatory.
+     */
+    String key(); // mandatory ;
+    /**
+     * Description of this kind of instances, is mandatory.
+     */
+    String description();
+
+    /**
+     * The class to instantiate, should have a default public constructor,
+     * so that type().newInstance() will work, is mandatory.
+     */
+    Class<?> type();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/Factory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+import java.lang.annotation.*;
+/**
+ * This annotation is coupled with {@link BasicObjectFactory} class,
+ * and allows one to create implementations of ObjectFactory via annotations.
+ * <pre> a simple example:
+&#064;Factory(description="dummy factory", default_value="array_list", placeholder_text="a type",
+classlist={
+&#064;FClass(description="a linked list", key="linked_list", type=LinkedList.class),
+&#064;FClass(description="an array  list", key="array_list", type=ArrayList.class)
+})
+public class BasicObjectFactoryUsageExample extends BasicObjectFactory<Collection>
+{
+}
+ * </pre>
+ * @see BasicObjectFactory
+ * @see FClass
+ * @see vm.share.options.test.BasicObjectFactoryUsageExample
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Factory
+{
+    final public static String defDefaultValue = "[no factory default]";
+    final public static String defDescription = "[no factory description]";
+    /**
+     * Used for generating placeholder text in <..> part of help message,
+     * is mandatory.
+     */
+    String placeholder_text(); // mandatory ;
+    /**
+     * Default value, used if the option is not specified AND if no default
+     * value has been specified in the corresponding @Option annotation.
+     */
+    String default_value() default defDefaultValue;
+
+    /**
+     * A help message string for the factory.
+     */
+    String description() default defDescription;
+
+    /**
+     * The list of classes and keys to instantiate.
+     * @see FClass
+     */
+    FClass[] classlist(); // mandatory
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/IgnoreUnknownArgumentsHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+public class IgnoreUnknownArgumentsHandler implements OptionHandler {
+
+    @Override public void option(String name, String value) {}
+    @Override public void argument(String value) {}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/ObjectFactory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options;
+
+/**
+ * This is a factory interface used to setup non-simple type options,
+ * implemented by the user, there is a shortcut, see {@link BasicObjectFactory}.
+ */
+public interface ObjectFactory<T>
+{
+    /**
+     * Returns a string that can be used in <..> section of help message.
+     * @return placeholder text
+     */
+    public String getPlaceholder();
+    /**
+     * Enumerates all possible key values for this factory.
+     * @return an array of keys
+     */
+    public String[] getPossibleValues();
+
+    /**
+     * Returns default description for options which use this factory
+     * @return the description string.
+     */
+    public String getDescription();
+
+
+    /**
+     * For a given parameter value gives its description.
+     * @param key to instantiate parameter
+     * @return description string for the parameter given.
+     */
+    public String getParameterDescription(String key);
+
+    /**
+     * Returns default value for the parameter, which is used if
+     * no default value attribute is defined at the @Option annotation level.
+     * @return default value for the parameter, null if mandatory
+     */
+    public String getDefaultValue();
+
+    /**
+     * Constructs an object given a object type key.
+     * @param key  name indicating the type of the object to create.
+     * @return the instance of the requested type
+     */
+    public T getObject(String key);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/Option.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+import java.lang.annotation.*;
+/**
+ * This annotation is the most useful one of the whole API.
+ * It is used to mark non-static fields of the object and to declare the
+ * corresponding options. The name of the option defaults to the name of the field.
+ * The help message for the option should also be also declared
+ * here (or it could be declared at the {@link ObjectFactory} level at any case it is mandatory).
+ * For non-simple option types a factory attribute should be provided which
+ * points to a class which implements {@link ObjectFactory} interface. That factory is
+ * then used to instantiate an object given the option value and to populate the
+ * annotated field.
+ *
+ * If a default value is provided it is used if the corresponding option is not declared
+ * at the command line. If it is not provided and there is no option then an error is thrown.
+ * For non-simple field types default values can be provided at ObjectFactory level.
+ * See also the documentation at the package level.).
+ */
+// kept at runtime, applied to fields only.
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Option
+{
+    // these strings help to find out if the corresponding attribute was not defined.
+    final public static String defName = "[no name]";
+    final public static String defDefaultValue = "[no default]";
+    final public static String defDescription = "[no description]";
+
+    /**
+     * The name of the option, defaults to the name of the annotated field.
+     */
+    String name() default defName;
+    /**
+     * The default value for the option, option is mandatory if it is not specified here
+     * and at the ObjectFactory level.
+     */
+    String default_value() default defDefaultValue;
+    /**
+     * A short description of the option used to generate a help message.
+     */
+    String description() default defDescription;
+
+    /**
+     * The factory class to use for instantiating the corresponding option.
+     */
+    Class<? extends OptionObjectFactory> factory() default OptionObjectFactory.class;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionDefinition.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.lang.reflect.Field;
+import nsk.share.TestBug;
+
+/**
+ * This is a "value" class for holding information about the defined options.
+ */
+public final class OptionDefinition {
+        private static final Map<String, OptionObjectFactory> factories = new HashMap<String, OptionObjectFactory>();
+        private String prefix;
+        private String name;
+        private String description;
+        private String defaultValue;
+        private Class<? extends OptionObjectFactory> factory;
+        private Field field;
+        private Object owner;
+
+        public OptionDefinition(String prefix, String name, String description, String defaultValue, Class<? extends OptionObjectFactory> factory, Field field, Object owner) {
+                this.prefix = prefix;
+                this.name = name;
+                this.description = description;
+                this.defaultValue = defaultValue;
+                this.factory = factory;
+                this.field = field;
+                this.owner = owner;
+        }
+
+        public String getPrefix() {
+                return prefix;
+        }
+
+        public String getName() {
+                return name;
+        }
+
+        public String getFullName() {
+                if (prefix != null)
+                        return prefix + "." + name;
+                else
+                        return name;
+        }
+
+        public Field getField() {
+                return field;
+        }
+
+        public Object getOwner() {
+                return owner;
+        }
+
+        public String getDescription() {
+                if (hasFactory())
+                        if (description == null)
+                                return getFactory().getDescription();
+                return description;
+        }
+
+        public String getDefaultValue() {
+                if (hasFactory())
+                        if (defaultValue == null)
+                                return getFactory().getDefaultValue();
+                return defaultValue;
+        }
+
+        public boolean hasFactory() {
+                return factory != null;
+        }
+
+        public String getPlaceHolder() {
+                if (hasFactory())
+                        return getFactory().getPlaceholder();
+                else
+                        return getField().getType().toString();
+        }
+
+        public synchronized OptionObjectFactory getFactory() {
+                if (factory == null)
+                        throw new TestBug("Called getFactory() on OptionDefinition with unset factory");
+                OptionObjectFactory factory = factories.get(this.factory);
+                if (factory == null) {
+                        try {
+                                factory = this.factory.newInstance();
+                        } catch (InstantiationException ex) {
+                                throw new TestBug("Failed to instantiate factory " + this.factory, ex);
+                        } catch (IllegalAccessException ex) {
+                                throw new TestBug("Failed to instantiate factory " + this.factory, ex);
+                        }
+                }
+                return factory;
+        }
+
+        public String toString() {
+                return "Option " + name + " field " + field + " object " + owner;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionError.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import nsk.share.TestBug;
+
+public class OptionError extends TestBug {
+        public OptionError(String msg, OptionDefinition optDef) {
+                super(msg + " (option definition: " + optDef + ")");
+        }
+
+        public OptionError(String msg, Throwable e, OptionDefinition optDef) {
+                super(msg + " (option definition: " + optDef + ")", e);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options;
+
+/**
+ * Handles options not specified via @Options annotations,
+ * implemented and provided by the user.
+ */
+public interface OptionHandler
+{
+        /**
+         * This method is called for every unknown option
+         * @param name option name (not including '-' or '=', trimmed)
+         * @param value may be null in the case of the last option with no value
+         * specified.
+         */
+        public void option(String name, String value);
+
+        /**
+         * This method is called for every command line argument which
+         * is not recognized as a part of -option_name=value pair.
+         * @param value the value of an unrecognized argument
+         */
+        public void argument(String value);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionObjectFactory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options;
+
+/**
+ * This is a factory interface used to setup non-simple type options,
+ * implemented by the user, there is a shortcut, see {@link BasicObjectFactory}.
+ */
+public interface OptionObjectFactory<T>
+{
+    /**
+     * Returns a string that can be used in <..> section of help message.
+     * @return placeholder text
+     */
+    public String getPlaceholder();
+
+    /**
+     * Enumerates all possible key values for this factory.
+     * @return an array of keys
+     */
+    public String[] getPossibleValues();
+
+    /**
+     * Returns default description for options which use this factory
+     * @return the description string.
+     */
+    public String getDescription();
+
+    /**
+     * For a given parameter value gives its description.
+     * @param key to instantiate parameter
+     * @return description string for the parameter given.
+     */
+    public String getParameterDescription(String key);
+
+    /**
+     * Returns default value for the parameter, which is used if
+     * no default value attribute is defined at the @Option annotation level.
+     * @return default value for the parameter, null if mandatory
+     */
+    public String getDefaultValue();
+
+    /**
+     * Constructs an object given a object type key.
+     * @param key  name indicating the type of the object to create.
+     * @return the instance of the requested type
+     */
+    public T getObject(String key);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionSupport.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+/**
+ * This class actually provides the OptionFramework API
+ * via two static {@link OptionSupport#setup} methods.
+ * See also "General description" section of the package level documentation.
+ */
+public class OptionSupport
+{
+    /**
+     * This method parses the commandline arguments, setups the instance fields (annotated by @Option) accordingly
+     * and calls method run().
+     * @param test  the instance to setup fields for
+     * @param args  command line arguments array
+      */
+    public static void setupAndRun(Runnable test, String[] args) {
+        setupAndRun(test, args, null);
+    }
+
+    /**
+     * This method parses the commandline arguments and setups the instance fields (annotated by @Option) accordingly
+     * @param test  the instance to setup fields for
+     * @param args  command line arguments array
+     */
+    public static void setup(Object test, String[] args)
+    {
+        setup(test, args, null);
+    }
+
+    /**
+     * This method parses the commandline arguments, setups the instance fields (annotated by @Option) accordingly
+     * and calls method run().
+     * @param test  the instance to setup fields for
+     * @param args  command line arguments array
+     * @param unknownOptionHandler an option handler for unknown options
+      */
+    public static void setupAndRun(Runnable test, String[] args, OptionHandler unknownOptionHandler) {
+        setup(test, args, unknownOptionHandler);
+        test.run();
+    }
+
+
+    /**
+     *  This is an extension API which allows Test author to create and
+     *  process some specific options.
+     * @param test  the instance to setup fields for
+     * @param args  command line arguments array
+     * @param unknownOptionHandler an option handler for unknown options
+     *
+     */
+    public static void setup(Object test, String[] args, OptionHandler unknownOptionHandler) {
+                new OptionsSetup(test, args, unknownOptionHandler).run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/Options.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * This annotation marks fields which should be scanned for @Option annotation,
+ * see the souurce code of {@link vm.share.options.test.SimpleExampleWithOptionsAnnotation}
+ * for detailed example.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Options {
+        // default value for undefined attribute
+        final public static String defPrefix = "[no prefix]";
+        /**
+         * The name of this group of option, added as prefix
+         */
+        String prefix() default defPrefix;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionsMap.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * This annotation marks fields of type Map<String, String>,
+ * where the name=>value map of given options is placed by the framework
+ *
+ * should be stored
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface OptionsMap { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/OptionsSetup.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Iterator;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.io.PrintStream;
+import nsk.share.TestBug;
+import nsk.share.log.LogSupport;
+
+class OptionsSetup {
+    private LogSupport log = new LogSupport();
+    private boolean verbose = true;
+    private Object test;
+    private String[] args;
+    private OptionHandler unknownOptionHandler;
+
+    private int argIndex = 0;
+    private Map<String, OptionDefinition> optionDefs = new LinkedHashMap<String, OptionDefinition>(); // Use LinkedHashMap to ensure order of options
+    private List<OptionDefinition> unconfiguredOptionsList = new ArrayList<OptionDefinition>();
+    private List<OptionDefinition> unconfiguredOptionList = new ArrayList<OptionDefinition>();
+    private Map<String, Object> optionValues = new LinkedHashMap<String, Object>();
+
+    public OptionsSetup(Object test, String[] args, OptionHandler unknownOptionHandler) {
+        this.test = test;
+        this.args = args;
+        this.unknownOptionHandler = unknownOptionHandler;
+        log.setDebugEnabled(verbose);
+    }
+
+    public void run() {
+        searchAnnotations(test, null);
+        while (argIndex < args.length) {
+            process1Arg();
+        }
+        setDefaultValues();
+        checkMandatoryOptions();
+        if (unconfiguredOptionsList.size() > 0) {
+            for (OptionDefinition optDef : unconfiguredOptionsList)
+                log.info("Unconfigured option: " + optDef);
+            throw new TestBug("Some options are unconfigured");
+        }
+    }
+
+    private void checkMandatoryOptions() {
+        for (Map.Entry<String, OptionDefinition> e : optionDefs.entrySet()) {
+            String name = e.getKey();
+            OptionDefinition optDef = e.getValue();
+            if (optDef.getDefaultValue() == null && !optionValues.containsKey(name))
+                throw new TestBug("Mandatory option is not specified: -" + name);
+        }
+    }
+
+    private void setDefaultValues() {
+        for (Iterator<OptionDefinition> it = unconfiguredOptionList.iterator(); it.hasNext(); ) {
+            OptionDefinition optDef = it.next();
+            String value = optDef.getDefaultValue();
+            if (value == null)
+                continue;
+            setOptionValue(optDef, value);
+            it.remove();
+            if (unconfiguredOptionsList.contains(optDef))
+                unconfiguredOptionsList.remove(optDef);
+        }
+
+        for (Iterator<OptionDefinition> it = unconfiguredOptionsList.iterator(); it.hasNext(); ) {
+            OptionDefinition optDef = it.next();
+            if (optionsAnnotation(optDef.getOwner(), optDef.getField(), null, optDef, true))
+                it.remove();
+        }
+    }
+
+    private void process1Arg() {
+        String arg = args[argIndex++];
+        //log.debug("Processing argument: " + arg);
+        if (!arg.startsWith("-")) {
+            processUnknownArg(arg);
+            return;
+        }
+        String opt = arg.substring(1);
+        String value = null;
+        int i = opt.indexOf('=');
+        if (i != -1) {
+            value = opt.substring(i + 1);
+            opt = opt.substring(0, i);
+        }
+        if (opt.equals("help")) {
+            printHelp();
+            throw new TestBug("-help was specified");
+        }
+        if (!optionDefs.containsKey(opt)) {
+            if (value == null && argIndex < args.length)
+                value = args[argIndex++];
+            // We need to try to resolve default values of all unconfigured fields because one of them may potentially have this option
+            setDefaultValues();
+            if (!optionDefs.containsKey(opt)) {
+                processUnknownOpt(opt, value);
+                return;
+            }
+        }
+        OptionDefinition optDef = optionDefs.get(opt);
+        Field f = optDef.getField();
+        // Handle boolean omitted value
+        if (value == null && (argIndex >= args.length || args[argIndex].startsWith("-"))) {
+            if (f.getType() == boolean.class || f.getType() == Boolean.class) {
+                value = "true";
+            }
+        }
+        if (value == null) {
+            if (argIndex >= args.length)
+                throw new TestBug("Missing value for option -" + opt);
+            value = args[argIndex++];
+        }
+        setOptionValue(optDef, value);
+        if (unconfiguredOptionList.contains(optDef)){
+            unconfiguredOptionList.remove(optDef);
+        }
+    }
+
+    private void setOptionValue(OptionDefinition optDef, String value) {
+        Object ovalue = null;
+        if (optDef.hasFactory()) {
+            ovalue = optDef.getFactory().getObject(value);
+        } else {
+            ovalue = PrimitiveParser.parse(value, optDef.getField().getType());
+        }
+        optionValues.put(optDef.getName(), ovalue);
+        try {
+            Field f = optDef.getField();
+            Object o = optDef.getOwner();
+            f.set(o, ovalue);
+            if (f.isAnnotationPresent(Options.class)) {
+                if (!optionsAnnotation(o, f, optDef.getPrefix(), optDef, false))
+                    throw new TestBug("Unexpected (bug in framework?): optionsAnnotation returned null: " + optDef);
+                if (unconfiguredOptionsList.contains(optDef))
+                    unconfiguredOptionsList.remove(optDef);
+            }
+        } catch (IllegalArgumentException e) {
+            throw new TestBug("Exception setting field value for option " + optDef.getName(), e);
+        } catch (IllegalAccessException e) {
+            throw new TestBug("Exception setting field value for option " + optDef.getName(), e);
+        }
+    }
+
+    private void processUnknownArg(String arg) {
+        if (unknownOptionHandler != null)
+            unknownOptionHandler.argument(arg);
+        else
+            throw new TestBug("Invalid argument: " + arg);
+    }
+
+    private void processUnknownOpt(String opt, String value) {
+        if (unknownOptionHandler != null)
+            unknownOptionHandler.option(opt, value);
+        else
+            throw new TestBug("Invalid option: '" + opt + "', value: '" + value + "'");
+    }
+
+    private void searchAnnotations(Object o, String prefix) {
+        Class<?> cl0 = o.getClass();
+        //log.debug("Looking for annotations for object " + o + ", class " + cl0);
+        List<Class> classes = new LinkedList<Class>();
+        while (cl0.getSuperclass() != null) {
+            classes.add(0, cl0); // Add to the beginning to ensure the option order is from superclass to subclass
+            cl0 = cl0.getSuperclass();
+        }
+        for (Class<?> cl : classes) {
+            for (Field f : cl.getDeclaredFields()) {
+                OptionDefinition optDef = null;
+                if (f.isAnnotationPresent(Option.class)) {
+                    optDef = optionAnnotation(o, f, prefix);
+                    if (optDef != null) {
+                        unconfiguredOptionList.add(optDef);
+                    }
+                }
+                if (f.isAnnotationPresent(Options.class)) {
+                    if (!optionsAnnotation(o, f, prefix, optDef, false)) {
+                        if (!unconfiguredOptionsList.contains(optDef))
+                            unconfiguredOptionsList.add(optDef);
+                    }
+                }
+            }
+        }
+    }
+
+    private boolean optionsAnnotation(Object o, Field f, String prefix, OptionDefinition optDef, boolean useDefault) {
+        if (Modifier.isStatic(f.getModifiers()))
+            throw new OptionError("@Options annotation is not allowed at static field", optDef);
+        if (!Object.class.isAssignableFrom(f.getDeclaringClass()))
+            throw new OptionError("@Options annotation is only allowed on object types", optDef);
+        //log.debug("Processing @Options annotation: object " + o + ", field " + f + ", prefix " + prefix);
+        Object v = null;
+        try {
+            f.setAccessible(true);
+            v = f.get(o);
+        } catch (IllegalAccessException e) {
+            throw new OptionError("Exception getting value of field ", e, optDef);
+        }
+        if (v == null) {
+            if (optDef == null)
+                throw new OptionError("Value of field is null and no @Option annotation is present", optDef);
+            if (!optDef.hasFactory())
+                throw new OptionError("Value of field is null and no @Option annotation does not have factory", optDef);
+            if (useDefault) {
+                setOptionValue(optDef, optDef.getDefaultValue());
+                try {
+                    v = f.get(o);
+                } catch (IllegalAccessException e) {
+                    throw new OptionError("Exception getting value of field ", e, optDef);
+                }
+            }
+            if (v == null) {
+                // We cannot setup it right away, so it is stored until value is set
+                return false;
+            } else
+                return true; // setOption Value already searched annotations
+        }
+        Options opts = f.getAnnotation(Options.class);
+        String vprefix = opts.prefix();
+        if (vprefix.equals(Options.defPrefix))
+            vprefix = null;
+        if (vprefix != null) {
+            if (prefix != null)
+                prefix = prefix + "." + vprefix;
+            else
+                prefix = vprefix;
+        }
+        searchAnnotations(v, prefix);
+        return true;
+    }
+
+    private OptionDefinition optionAnnotation(Object o, Field f, String prefix) {
+        //log.debug("Processing @Option annotation: object " + o + ", field " + f + ", prefix " + prefix);
+        f.setAccessible(true);
+        Option opt = f.getAnnotation(Option.class);
+        String name = opt.name();
+        if (name.equals(Option.defName))
+            name = f.getName();  // option name defaults to field name
+        if (prefix != null)
+            name = prefix + "." + name;
+        if (optionDefs.containsKey(name))
+            throw new TestBug("Option is already defined: " + name);
+        String defaultValue = opt.default_value();
+        if (defaultValue.equals(Option.defDefaultValue))
+            defaultValue = null; // default value defaults to null
+        String description = opt.description();
+        if (description.equals(Option.defDescription))
+            description = null;
+        if (description == null) {
+            if (name.equals("log") || name.endsWith(".log")) {
+                try {
+                    f.set(o, log);
+                } catch (IllegalAccessException e) {
+                    throw new TestBug("Exception setting log field of " + o, e);
+                }
+                return null;
+            } else
+                throw new TestBug("@Option annotation should always have description set: " + name + ", field: " + f);
+        }
+        Class<? extends OptionObjectFactory> factory = opt.factory();
+        //log.debug("Factory: " + factory);
+        if (factory.equals(OptionObjectFactory.class))
+            factory = null;
+        OptionDefinition optDef = new OptionDefinition(
+                prefix,
+                name,
+                description,
+                defaultValue,
+                factory,
+                f,
+                o
+        );
+        optionDefs.put(name, optDef);
+        //log.debug("Added option definition: " + optDef);
+        return optDef;
+    }
+
+    private void printHelp() {
+        PrintStream out = System.out;
+        out.println(" Supported options:");
+        out.println("    -help");
+        out.println("          Show this help screen");
+        for (Map.Entry<String, OptionDefinition> entry : optionDefs.entrySet()) {
+            String opt = entry.getKey();
+            OptionDefinition optDef = entry.getValue();
+            out.println("    -" + opt + " <" + optDef.getPlaceHolder() + ">");
+            out.print("          " + optDef.getDescription() + " ");
+            if (optDef.getDefaultValue() != null) {
+                out.println("(default: " + optDef.getDefaultValue() + ")");
+            } else {
+                out.println("(mandatory)");
+            }
+            if (optDef.hasFactory()) {
+                OptionObjectFactory factory = optDef.getFactory();
+                for (String key : factory.getPossibleValues()) {
+                    out.println("             " + key + ": " + factory.getParameterDescription(key));
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/ParserException.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.options;
+
+import nsk.share.TestBug;
+
+/**
+  * This class represents a simple Parser exception.
+  */
+public class ParserException extends TestBug {
+        public ParserException(String message, Throwable cause) {
+                super(message, cause);
+        }
+
+        public ParserException(String message) {
+                super(message);
+        }
+
+        public ParserException(Throwable cause) {
+                super(cause);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/PrimitiveParser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package vm.share.options;
+
+import java.lang.reflect.Array;
+import java.util.HashMap;
+import java.util.Map;
+import nsk.share.TestBug;
+
+/**
+ * A utility class used to parse arguments of various primitive types.
+ */
+public class PrimitiveParser
+{
+    /**
+     * Checks if the parser can handle passed type ("primitive/wrapper" or one-dim array of those).
+     * Note that one-dim arrays of primitives/strings/wrappers are also supported.
+     * @param type the type to parse against
+     * @return true, if can parse.
+     */
+    public static boolean canHandle(Class<?> type)
+    {
+
+        if(type.isArray())
+        {
+            Class<?> compType = type.getComponentType();
+            if(compType.isArray()) return false; // Cannot handle multidimensional arrays
+            return canHandle(compType);
+        }
+        type = convertPrimitiveTypeToWrapper(type);
+        return parsers.containsKey(type);
+    }
+
+    /**
+     * A simple helper method.
+     * @param type the type to check for
+     * @return the parser to use, null if there is none.
+     */
+    private static PParser getParser(Class<?> type)
+    {
+        return parsers.get(convertPrimitiveTypeToWrapper(type));
+    }
+
+    /**
+     * The main API method of this class.
+     * @param param the parameter to parse
+     * @param type parameter type to parse against
+     * @return returns the object of a given type.
+     * @throws vm.share.options.PrimitiveParser.ParserException
+     */
+    public static Object parse(String param, Class<?> type) throws ParserException
+    {
+        if(type.isArray())
+        {
+            Class<?> compType = type.getComponentType();
+            if(compType.isArray())
+              throw new ParserException("Cannot handle multidimensional arrays");
+
+            if(!canHandle(compType))
+                throw new ParserException("Unable to parse unknown array component type " + compType);
+
+            String[] params = param.split(",");
+            Object arr = Array.newInstance(compType, params.length);
+            for (int i = 0; i < params.length; i++)
+            {
+                String par = params[i].trim();
+                Array.set(arr, i, parse(par, compType));
+            }
+            return arr;
+        }
+        else
+        {
+            if(!canHandle(type))
+                throw new ParserException("Unable to parse unknown type " + type);
+            return getParser(type).parse(param);
+        }
+    }
+
+    // I'm not sure, if generics are of any use here...
+    static private abstract class PParser<T>
+    {
+        abstract T parse(String param) throws ParserException;
+
+//        Class<T> getClassKey()
+//        {
+//            return PrimitiveParser.(Class<T>) T.getClass();
+//        }
+    }
+
+    /**
+     * Converts primitive types to corresponding wrapper classes.
+     * We could register int.class, boolean.class etc in the hashtable instead.
+     * (Or Integer.TYPE, etc.)
+     * @param type to convert to wrapper
+     * @return wrapper class or type if it is not primitive
+     */
+    public static Class<?> convertPrimitiveTypeToWrapper(Class<?> type)
+    {
+        if(!type.isPrimitive()) return type;
+         Object arr = Array.newInstance(type, 1);
+         Object v = Array.get(arr, 0);
+         return v.getClass();
+    }
+
+
+    //"kind of state" machine stuff
+
+    private static Map<Class<?>, PParser<?>> parsers;
+
+    static
+    {
+        parsers = new HashMap<Class<?>, PrimitiveParser.PParser<?>>(16);
+        parsers.put(Integer.class, new PParser<Integer>()
+        {
+            @Override Integer parse(String param) throws ParserException
+            {
+                if ( param.startsWith("0x") )
+                    return Integer.parseInt(param.substring(2));
+                else
+                    return Integer.valueOf(param);
+            }
+        });
+        parsers.put(Boolean.class, new PParser<Boolean>()
+        {
+            @Override Boolean parse(String param) throws ParserException
+            {
+                //special behavior for options
+                if(param == null) return true;
+                if(param.trim().length()==0) return true;
+                return Boolean.valueOf(param);
+            }
+        });
+
+        parsers.put(String.class, new PParser<String>()
+        {
+            @Override String parse(String param) throws ParserException
+            {
+                if(param == null) throw new ParserException(" Got null value string.");
+                return param;
+            }
+        });
+
+
+        parsers.put(Character.class, new PParser<Character>()
+        {
+            @Override Character parse(String param) throws ParserException
+            {
+               if(param.length()!=1)
+                    throw new TestBug("Found Character type option of length != 1");
+               return  Character.valueOf(param.charAt(0));
+            }
+        });
+
+        parsers.put(Byte.class, new PParser<Byte>()
+        {
+            @Override Byte parse(String param) throws ParserException
+            {
+                if ( param.startsWith("0x") )
+                    return Byte.parseByte(param.substring(2));
+                else
+                    return Byte.valueOf(param);
+            }
+        });
+
+        parsers.put(Short.class, new PParser<Short>()
+        {
+            @Override Short parse(String param) throws ParserException
+            {
+                if ( param.startsWith("0x") )
+                    return Short.parseShort(param.substring(2));
+                else
+                    return Short.valueOf(param);
+            }
+        });
+
+        parsers.put(Long.class, new PParser<Long>()
+        {
+            @Override Long parse(String param) throws ParserException
+            {
+                if ( param.startsWith("0x") )
+                    return Long.parseLong(param.substring(2));
+                else
+                    return Long.valueOf(param);
+            }
+        });
+
+        parsers.put(Float.class, new PParser<Float>()
+        {
+            @Override Float parse(String param) throws ParserException
+            {
+                return Float.valueOf(param);
+            }
+        });
+
+        parsers.put(Double.class, new PParser<Double>()
+        {
+            @Override Double parse(String param) throws ParserException
+            {
+                return Double.valueOf(param);
+            }
+        });
+    }
+
+
+/* Discussion
+ * 1. It was proposed to use instead of the convertPrimitive the following
+ *
+ *   private static Map<Class<?>, Class<?>> wrapperClasses = new HashMap<Class<?>, Class<?>>();
+ *
+ *  so we could do    if(type.isPrimitive())
+                type = wrapperClasses.get(type);
+    static {
+        wrapperClasses.put(boolean.class, Boolean.class);
+        wrapperClasses.put(short.class, Short.class);
+        wrapperClasses.put(int.class, Integer.class);
+        wrapperClasses.put(Long.Type, Long.class);   // we can do it this way!
+        wrapperClasses.put(float.class, Float.class);
+        wrapperClasses.put(double.class, Double.class);
+    }
+ * The alternative is to register PParsers with corresponding Primitive type too.
+ *
+ * Also canHandle() could use
+     return wrapperClasses.keySet().contains(type) || wrapperClasses.entrySet().contains(type);
+
+ *  2. Parsing can be implemented via reflection
+    return type.getMethod("valueOf", new Class[]{String.class}).invoke(null, string);
+
+ *   I don't like using reflection as it prevents optimisation,
+ *   also now Strings and Characters are handled in a nice fashion.
+ *
+ * As for convertToPrimitive trick both ways are good,
+ * but current looks more generic though tricky
+ */
+
+//// some test, should it be commented out?
+//    public static void main(String[] args)
+//    {
+//        try
+//        {
+//            String str = "0";
+//            Object o = null;
+//            str = "0";
+//            o = parse(str, String.class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//
+//            str = "0";
+//            o = parse(str, int.class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//            str = "0";
+//            o = parse(str, Integer.class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//
+//            str = "0,1,2";
+//            o = parse(str, int[].class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + (int[]) o + "#");
+//            System.out.println("DATA:" + java.util.Arrays.toString((int[])o));
+//            //            System.out.println("DATA:" + java.util.Arrays.deepToString( (int[]) o));
+//
+//            str = "0";
+//            o = parse(str, byte.class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//
+//            str = "0";
+//            o = parse(str, HashMap.class);
+//            System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+////         String str = "0"; Object o = parsePrimitiveString(help_option, type); System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//        } catch (ParserException ex)
+//        {
+//            System.out.println("" +ex);
+//        }
+////         String str = "0"; Object o = parsePrimitiveString(help_option, type); System.out.println("value:" + str + " type: " + o.getClass() + " value:#" + o + "#");
+//
+//    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/package-info.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * This framework allows one to automate parsing of the test command line
+ * arguments (it automatically sets the corresponding fields of the
+ * test class).
+ <p>
+<h3>A simplified example</h3>
+Suppose we want to to define a test Test with an option "iterations",
+which can be run via
+</p>
+<pre> > java Test -iterations 10 </pre>
+or via
+<pre> java Test </pre>
+in the last case iterations defaults to 100.
+<p>
+We want to achieve this by annotating fields of the Test class by
+a special @Option annotation.
+<p>
+For simplicity suppose @Option is defined as follows:
+<pre>
+ &#064;interface Option
+ { //here all the annotation fields are mandatory
+        String name();
+        String default();
+        String description();
+ }
+ </pre>
+ The test class uses an API like:
+ <pre>
+     public class OptionSupport {
+     public static void setup(Object test, String[] args);
+ }
+</pre>
+Now a simple example:
+<pre>
+public class Test {
+
+    &#064;Option( name="iterations",
+                 default="100",
+                 description="Number of iterations")
+    int iterations;
+    public void run() {
+        // ..do actual testing here..
+    }
+
+    public static void main(String args) {
+        Test test = new Test();
+        OptionsSupport.setup(test, args); // instead of manually
+                      // parsing arguments
+        // now test.iterations is set to 10 or 100.
+        test.run();
+    }
+}
+</pre>
+This test can be also run via
+<pre>
+- java Test -help
+</pre>
+Then OptionSupport.setup() shows
+help and exits (by throwing exception?):
+<pre>
+   Supported options:
+    -iterations <number>
+              Number of iterations (mandatory)
+</pre>
+We also want to be able to apply this to fields of non-simple types (via
+factories) and  to other classes recursively (see @Options annotation
+below).
+<p>
+Please, see {@link vm.share.options.test.SimpleExample}
+for a working version of this.
+ * <h3> General description </h3>
+ Options are defined using annotations like this:
+<pre>
+public class StressOptions {
+    // [2]
+    &#064;Option(name="stressTime",
+                default_value="60",
+                description="Stress time")
+    private long stressTime;
+
+    ...
+}
+</pre>
+<p> we want to use command line like
+<pre> java Test -stressTime 50 </pre>
+here 50 is passed to the StressOptions.stressTime field.
+see {@link vm.share.options.Options} below. </p>
+<pre>
+public class Test {
+    // [1]
+    &#064;Options
+    StressOptions stressOptions = new StressOptions();
+
+    // [2]
+    &#064;Option(name="iterations",
+                default_value="100",
+                description="Number of iterations")
+    int iterations;
+
+    // [3]
+    &#064;Option(
+        name="garbageProducer",
+        default="byteArr",
+        description="Garbage  producer",
+        factory="nsk.share.gc.gp.GarbageProducerFactory")
+    GarbageProducer garbageProducer;
+...
+
+    // [4]
+    &#064;Option(name="logger",
+         description="Logger",
+     factory="nsk.share.log.LogFactory")
+    Log log;
+
+    public void run() {
+        log.info("Start test");
+        log.info("Finish test");
+    }
+
+    public static void main(String[] args) {
+        Test test = new Test();
+        OptionsSupport.setup(test, args);
+        test.run();
+    }
+}
+</pre>
+<p> The API is invoked via a call to {@link vm.share.options.OptionSupport#setup(Object, String[])}).
+ Also there is {@link vm.share.options.OptionSupport#setup(Object, String[], OptionHandler)}) method.
+ It allows the caller to pass a handler which takes
+ care of the options not defined via @Option annotation.
+</p>
+
+<h3>Requirements</h3>
+<p>
+ - The following field types are supported out-of-box: [2]
+   <ul>
+   <li/>All basic (primitive) types (int, long, ...) and corresponding wrapper types.
+   <li/> In the case of a boolean type option user is allowed to skip second argument,
+        i.e. write '-option_name'
+        instead of '-option_name true'.
+   <li/> Strings.
+   <li/> One dimentional arrays of the above (comma-separated).
+   <li/> Classes if a factory is specified, see below.
+        <emph>NOTE: currently there is no way to pass some options to the instantiated objects.</emph>
+   </ul>
+</p>
+<p> All non-static fields (including private and protected) of class and
+    it's superclasses are scanned for annotations.
+</p>
+<p>
+ (Possibly) Same annotations for setter methods ? (NOT IMPLEMENTED)
+</p>
+<p>
+  It is possible to inherit options of the field type
+  through @Options annotations, see {@link vm.share.options.Options}, and [1] above.
+</p>
+<p>
+ Option.name defaults to the name of the field.
+</p>
+<p> Object options are supported using {@link vm.share.options.OptionObjectFactory}, see [3] above.
+Please see {@link vm.share.options.OptionObjectFactory} interface, it should be
+implemented by the user and specified in the Option.factory attribute.
+</p>
+<p>
+As a shortcut we provide BasicOptionObjectFactory class, which allows user to
+create a factory via @{@link vm.share.options.Factory} annotation:
+<pre>
+&#064;Factory (
+    placeholder_text="garbage producer", //used for generating <..> in the help message
+    default_value="byteArr",
+    classlist={
+        &#064;FClass(key="byteArr",
+                     type="nsk.share.gc.gp.array.ByteArrayProducer",
+                     description="byte array producer")
+        &#064;FClass(key="charArr",
+                     type="nsk.share.gc.gp.array.CharArrayProducer",
+                     description="char array producer")
+        ...
+    }
+)
+public class GarbageProducerFactory extends BasicOptionObjectFactory {
+}
+</pre>
+<p> <emph> note: for subclasses of BasicOptionObjectFactory
+factories can extend each other!!
+so the check for @OptionObjectFactory is done recursively.
+NOT SURE IF THIS IS IMPLEMENTED.
+</emph></p>
+<p> If there is no unknownOptionHandler then in case of unsupported
+option, a Runtime exception is thrown.
+</p>
+<p>
+ If there is no 'default' annotation attribute and there is no default
+for OptionObjectFactory, then option is mandatory and a Runtime exception is thrown if
+it's missing.
+</p>
+ <p> Both '-option value' and '-option=value' formats are supported.
+ </p>
+<p> If main class is given '-help', OptionSupport.setup() shows
+help and exits (by throwing a Runtime exception):
+<pre>
+Supported options:
+    -iterations <number>
+              Number of iterations (mandatory)
+        -stressTime <number>
+              Stress time (default 60)
+    -garbageProducer <garbage producer>
+              Garbage producer (default byteArr). Supported keys:
+                  byteArr    byte array producer
+                  charArr    char array producer
+                  ...
+        ...
+</pre>
+
+<p> <emph> NOT IMPLEMENTED: </emph>
+Integer type boundaries are validated with RuntimeException with detailed
+meaningful error message. Other validations that are possible are also done.
+</p>
+ <p> <emph> NOT IMPLEMENTED: </emph>
+ Empty default ("") value for Object annotations [3] means null value.
+</p>
+<p> The object created via factory is also scanned for @Option annotations
+(like in the @Options case), i.e. it inherits options from the Test class.
+<emph> This is not implemented as it causes several problems, in particular, the
+object must be instanciated in order to be scanned for options, hence no meaningful
+help message could be generated for corresponding options.
+One of the possible solutions
+is to allow -object_opt_name.suboption syntax (or even with a colon), and to pass the
+corresponding suboptions Map to the OptionObjectFactory, it could use OptionFramework
+to take care of it. It is unclear, what other problems can arise.</emph>
+</p>
+ *
+ */
+package vm.share.options;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/BasicObjectFactoryUsageExample.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package vm.share.options.test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import vm.share.options.BasicOptionObjectFactory;
+import vm.share.options.FClass;
+import vm.share.options.Factory;
+
+/**
+ * This is a simple example of BasicObjectFactory utility class,
+ * which allows us to produce {@link vm.share.options.ObjectFactory}
+ * implementations via annotations.
+ * @see vm.share.options.ObjectFactory
+ * @see vm.share.options.BasicObjectFactory
+ * @see vm.share.options.Factory
+ * @see vm.share.options.FClass
+ */
+@Factory(description="dummy factory", default_value="array_list", placeholder_text="a type",
+classlist={
+@FClass(description="a linked list", key="linked_list", type=LinkedList.class),
+@FClass(description="an array  list", key="array_list", type=ArrayList.class)
+})
+        // MUST BE PUBLIC or it could not be istantiated!!
+public class BasicObjectFactoryUsageExample extends BasicOptionObjectFactory<Collection>
+{
+
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/ExampleWithNonprimitiveOptions.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package vm.share.options.test;
+
+import java.util.Collection;
+import vm.share.options.Option;
+import vm.share.options.OptionSupport;
+
+/**
+ * This example uses @Option annotation with an a factory attribute,
+ * to populate a field of a non-simple type.
+ */
+public class ExampleWithNonprimitiveOptions
+{
+
+    @Option(name = "iterations", default_value = "100", description = "Number of iterations")
+    int iterations;
+
+
+    @Option(description = "quiet or verbose")
+    private String running_mode;
+
+    @Option(description = "type of the list",
+            factory=vm.share.options.test.BasicObjectFactoryUsageExample.class)
+    private Collection list;
+
+    public void run()
+    {
+    // ..do actual testing here..
+         System.out.println("iterations = " + iterations);
+         System.out.println("RM : " + running_mode);
+         System.out.println("list is " + list.getClass());
+    }
+
+
+    public static void main(String[] args)
+    {
+        ExampleWithNonprimitiveOptions test = new ExampleWithNonprimitiveOptions();
+        OptionSupport.setup(test, args); // instead of manually                       // parsing arguments
+        // now test.iterations is set to 10 or 100.
+        test.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/SimpleExample.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * This is a very simple test for our framework.
+ */
+package vm.share.options.test;
+
+import vm.share.options.Option;
+import vm.share.options.OptionSupport;
+
+/**
+ * This is a very simple usage example of the framework
+ * @see vm.share.options.Option
+ * @see vm.share.options.OptionSupport
+ */
+public class SimpleExample
+{
+
+    @Option(name = "iterations", default_value = "100", description = "Number of iterations")
+    int iterations;
+
+
+    @Option(description = "quiet or verbose")
+    private String running_mode;
+
+    public void run()
+    {
+    // ..do actual testing here..
+         System.out.println("iterations = " + iterations);
+         System.out.println("RM : " + running_mode);
+    }
+
+
+    public static void main(String[] args)
+    {
+        SimpleExample test = new SimpleExample();
+        OptionSupport.setup(test, args); // instead of manually
+                                         // parsing arguments
+        // now test.iterations is set to 10 or 100 (default value).
+        test.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/SimpleExampleWithOptionsAnnotation.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package vm.share.options.test;
+
+import vm.share.options.Option;
+import vm.share.options.OptionSupport;
+import vm.share.options.Options;
+
+
+/**
+ * This is again a simple example which shows the power of @Options annotation.
+ * @see vm.share.options.Options
+ * @see vm.share.options.Option
+ * @see vm.share.options.OptionSupport
+ */
+
+public class SimpleExampleWithOptionsAnnotation
+{
+    @Options
+    StressOptions stressOptions = new StressOptions();
+    @Option(name = "iterations", default_value = "100", description = "Number of iterations")
+    int iterations;
+
+    @Option(description = "quiet or verbose")
+    String running_mode;
+
+    public void run()
+    {
+    // ..do actual testing here..
+         System.out.println("iterations = " + iterations);
+         System.out.println("RM: " + running_mode);
+         System.out.println("StressOptions " + stressOptions.getStressTime());
+    }
+
+
+    public static void main(String[] args)
+    {
+        SimpleExampleWithOptionsAnnotation test = new SimpleExampleWithOptionsAnnotation();
+        OptionSupport.setup(test, args); // instead of manually                       // parsing arguments
+        // now test.iterations is set to 10 or 100.
+        test.run();
+    }
+}
+
+class StressOptions
+{
+    @Option(default_value="60", description="Stress time")
+    private long stressTime;
+
+    public long getStressTime()
+    {
+        return stressTime;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/SubClassExample.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * This is a very simple test for our framework.
+ */
+package vm.share.options.test;
+
+import vm.share.options.Option;
+import vm.share.options.OptionSupport;
+
+/**
+ * This is an example with annotated superclasses
+ * @see vm.share.options.Option
+ * @see vm.share.options.OptionSupport
+ */
+public class SubClassExample extends SimpleExampleWithOptionsAnnotation
+{
+
+    @Option(name = "timeout", default_value = "100", description = "timeout")
+    int timeout;
+
+
+    @Option(name = "logging_mode", description = "quiet or verbose")
+    private String logging_mode;
+
+    @Override
+    public void run()
+    {
+    // ..do actual testing here..
+         System.out.println("iterations = " + iterations);
+         System.out.println("RM : " + running_mode);
+         System.out.println("logging_mode" + logging_mode);
+         System.out.println("timeout " + timeout);
+         System.out.println("stresstime " + stressOptions.getStressTime());
+    }
+
+
+    public static void main(String[] args)
+    {
+        SubClassExample test = new SubClassExample();
+        OptionSupport.setup(test, args); // instead of manually
+                                         // parsing arguments
+        // now test.iterations is set to 10 or 100 (default value).
+        test.run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/options/test/package-info.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+
+ */
+/**
+ * This package contains a number of short examples which demonstrate
+ * the most typical usage use this API, please, take a look at the source code.
+ */
+package vm.share.options.test;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/CmdExecutor.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.io.IOException;
+import java.util.Collection;
+
+public class CmdExecutor extends ProcessExecutor {
+    private final StringBuilder cmd = new StringBuilder();
+    @Override
+    public void clearArgs() {
+        cmd.setLength(0);
+    }
+
+    @Override
+    public void addArg(String arg) {
+        cmd.append(" " + arg);
+    }
+
+    @Override
+    public void addArgs(String[] args) {
+        for (String arg : args) {
+            addArg(arg);
+        }
+    }
+
+    @Override
+    public void addArgs(Collection<String> args) {
+        for (String arg : args) {
+            addArg(arg);
+        }
+    }
+
+    @Override
+    protected Process createProcess() throws IOException {
+        return Runtime.getRuntime().exec(cmd.toString());
+    }
+
+    @Override
+    public String toString() {
+        return cmd.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/MessageInput.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.util.List;
+
+public interface MessageInput {
+        public boolean waitForStart(long timeout) throws InterruptedException;
+        public boolean waitForMessage(long timeout) throws InterruptedException;
+        public boolean waitForMessage(String msg, long timeout) throws InterruptedException;
+        public String getMessage();
+        public List<String> getMessages();
+        public List<String> getMessages(int to);
+        public List<String> getMessages(int from, int to);
+        public boolean waitForFinish(long timeout) throws InterruptedException;
+        public void reset();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/MessageOutput.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+public interface MessageOutput {
+        public void start();
+        public void send(String msg);
+        public void finish();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessExecutor.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import nsk.share.TestBug;
+import nsk.share.TestFailure;
+import nsk.share.log.Log;
+import vm.share.ProcessUtils;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.lang.reflect.Field;
+
+public class ProcessExecutor {
+    private static long CLEANUP_TIMEOUT = 60000;
+    private Process process;
+    private StreamReader stdoutReader = new StreamReader("stdout");
+    private StreamReader stderrReader = new StreamReader("stderr");
+    private Waiter waiter = new Waiter();
+    private OutputStream stdin;
+    private volatile boolean running;
+    private volatile int result = -1;
+    private List<String> args = new ArrayList<String>();
+
+    public int getResult() {
+        return result;
+    }
+
+    public void clearArgs() {
+        this.args.clear();
+    }
+
+    public void addArg(String arg) {
+        this.args.add(arg);
+    }
+
+    public void addArgs(String[] args) {
+        for (String arg : args) {
+            this.args.add(arg);
+        }
+    }
+
+    public void addArgs(Collection<String> args) {
+        this.args.addAll(args);
+    }
+
+    private void printCommandLine() {
+        for (String arg : args) {
+            System.out.println(arg);
+        }
+    }
+
+    /*
+     * Start process.
+     */
+    public void start() {
+        if (process != null) {
+            throw new TestBug("Process is already started");
+        }
+        printCommandLine();
+        try {
+            process = createProcess();
+            stdoutReader.setDescription("stdout: " + toString());
+            stdoutReader.setStream(process.getInputStream());
+            stderrReader.setDescription("stderr: " + toString());
+            stderrReader.setStream(process.getErrorStream());
+            stdin = process.getOutputStream();
+            stdoutReader.start();
+            stderrReader.start();
+            waiter.start();
+        } catch (IOException e) {
+            throw new TestFailure("Error running process: " + toString(), e);
+        }
+    }
+
+    protected Process createProcess() throws IOException {
+        String[] commandLine = args.toArray(new String[args.size()]);
+        return Runtime.getRuntime().exec(commandLine);
+    }
+
+    /**
+     * Run and wait for completion.
+     */
+    public int execute(long timeout) {
+        if (timeout <= 0) {
+            throw new TestBug("Positive timeout is required");
+        }
+        start();
+        return waitFor(timeout);
+    }
+
+    public int waitFor(long timeout) {
+        if (process == null) {
+            throw new TestBug("Process is not yet started");
+        }
+        if (timeout <= 0) {
+            throw new TestBug("Positive timeout is required");
+        }
+        long timeleft = timeout;
+        long startTime = 0;
+        while (timeleft > 0) {
+            try {
+                startTime = System.currentTimeMillis();
+                waiter.join(timeout);
+                return result;
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            timeleft -= (System.currentTimeMillis() - startTime);
+        }
+        return -1;
+    }
+
+    public int getPid() {
+        return ProcessUtils.getPid(process);
+    }
+
+    public OutputStream getStdIn() {
+        if (process == null) {
+            throw new TestBug(
+                    "Process is not running; prepare writers after it is started");
+        }
+        return stdin;
+    }
+
+    public PrintStream getStdInPrint() {
+        return new PrintStream(getStdIn(),
+                true); // Autoflush is important here.
+    }
+
+/*
+    public InputStream getStdOut() {
+                if (process != null)
+                        throw new TestBug("Process is already running; prepare readers before it is started or some output may be missed");
+                return stdoutReader.getInputStream();
+        }
+
+        public BufferedReader getStdOutReader() {
+                return new BufferedReader(new InputStreamReader(getStdOut()));
+        }
+
+        public InputStream getStdErr() {
+                if (process != null)
+                        throw new TestBug("Process is already running; prepare readers before it is started or some output may be missed");
+                return stderrReader.getInputStream();
+        }
+
+        public BufferedReader getStdErrReader() {
+                return new BufferedReader(new InputStreamReader(getStdOut()));
+        }
+
+        public String getStdoutOutput() {
+                if (stdoutReader == null)
+                        throw new TestBug("Process is not running");
+                return stdoutReader.getOutput();
+        }
+
+        public String getStderrOutput() {
+                if (stderrReader == null)
+                        throw new TestBug("Process is not running");
+                return stderrReader.getOutput();
+        }
+        */
+
+    public void addStdOutListener(StreamListener l) {
+        stdoutReader.addListener(l);
+    }
+
+    public void addStdErrListener(StreamListener l) {
+        stderrReader.addListener(l);
+    }
+
+    public void logStdOut(String prefix, Log log) {
+        stdoutReader.addListener(new StreamLogger(prefix, log));
+    }
+
+    public void logStdErr(String prefix, Log log) {
+        stderrReader.addListener(new StreamLogger(prefix, log));
+    }
+
+    public void logStdOutErr(String prefix, Log log) {
+        logStdOut(prefix, log);
+        logStdErr("(stderr)" + prefix, log);
+    }
+
+    public boolean isStarted() {
+        return (process != null);
+    }
+
+    public void kill() {
+        if (process == null) {
+            throw new TestBug("Process is not running");
+        }
+        process.destroy();
+        if (stdoutReader != null) {
+            stdoutReader.kill();
+        }
+        if (stderrReader != null) {
+            stderrReader.kill();
+        }
+        if (waiter != null && waiter.isAlive()) {
+            waiter.kill();
+        }
+        process = null;
+    }
+
+    public void finish() {
+        if (stdoutReader != null) {
+            try {
+                stdoutReader.join(CLEANUP_TIMEOUT);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            stdoutReader = null;
+        }
+        if (stderrReader != null) {
+            try {
+                stderrReader.join(CLEANUP_TIMEOUT);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            stderrReader = null;
+        }
+        process = null;
+    }
+
+    public String toString() {
+        String ts = "";
+        if (args != null) {
+            for (String s : args) {
+                ts += s;
+                ts += " ";
+            }
+        }
+        return ts;
+    }
+
+    private class Waiter extends Thread {
+        public Waiter() {
+            super("Process Waiter: (not setup)");
+            setDaemon(true);
+        }
+
+        public void run() {
+            setName("Process Waiter: " + ProcessExecutor.this);
+            try {
+                result = process.waitFor();
+            } catch (InterruptedException e) {
+                // Ignore
+            }
+        }
+
+        public void kill() {
+            this.interrupt();
+            long timeleft = CLEANUP_TIMEOUT;
+            long startTime = 0;
+            while (timeleft > 0) {
+                try {
+                    startTime = System.currentTimeMillis();
+                    this.join(timeleft);
+                    return;
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                timeleft -= (System.currentTimeMillis() - startTime);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/ProcessHandler.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.util.List;
+
+public class ProcessHandler implements MessageInput, MessageOutput {
+        private StreamMessageInput stdout = new StreamMessageInput();
+        private StreamMessageInput stderr = new StreamMessageInput();
+        private StreamMessageOutput stdin = new StreamMessageOutput();
+
+        public ProcessHandler() {
+        }
+
+        public ProcessHandler(ProcessExecutor exec) {
+                bind(exec);
+        }
+
+        public void bind(ProcessExecutor exec) {
+                exec.addStdOutListener(stdout.createListener());
+                exec.addStdErrListener(stderr.createListener());
+                exec.start();
+                stdin.bind(exec.getStdIn());
+        }
+
+        public boolean waitForStart(long timeout) throws InterruptedException {
+                return stdout.waitForStart(timeout) && stderr.waitForStart(timeout);
+        }
+
+        public boolean waitForMessage(long timeout) throws InterruptedException {
+                return stdout.waitForMessage(timeout);
+        }
+
+        public boolean waitForMessage(String msg, long timeout) throws InterruptedException {
+                return stdout.waitForMessage(msg, timeout);
+        }
+
+        public String getMessage() {
+                return stdout.getMessage();
+        }
+
+        public List<String> getMessages() {
+                return stdout.getMessages();
+        }
+
+        public List<String> getMessages(int to) {
+                return stdout.getMessages(to);
+        }
+
+        public List<String> getMessages(int from, int to) {
+                return stdout.getMessages(from, to);
+        }
+
+        public boolean waitForStdErrMessage(String msg, long timeout) throws InterruptedException {
+                return stderr.waitForMessage(msg, timeout);
+        }
+
+        public String getStdErrMessage() {
+                return stderr.getMessage();
+        }
+
+        public boolean waitForFinish(long timeout) throws InterruptedException {
+                return stdout.waitForFinish(timeout) && stderr.waitForFinish(timeout);
+        }
+
+        public void start() {
+                stdin.start();
+        }
+
+        public void send(String msg) {
+                stdin.send(msg);
+        }
+
+        public void finish() {
+                stdin.finish();
+        }
+
+        public void reset() {
+                stdout.reset();
+                stderr.reset();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamListener.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+/*
+ * StreamListener listens on events from BufferedInputStream.
+ *
+ * Note: StreamListener should not never block as it potentially
+ * runs in thread that reads the input.
+ */
+public interface StreamListener {
+        public void onStart();
+        public void onRead(String line);
+        public void onFinish();
+        public void onException(Throwable e);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamLogger.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import nsk.share.log.Log;
+
+/*
+ * StreamListener that logs everything to Log at debug priority.
+ */
+public class StreamLogger implements StreamListener {
+        private String prefix;
+        private Log log;
+
+        public StreamLogger(String prefix, Log log) {
+                this.prefix = prefix;
+                this.log = log;
+        }
+
+        public void onStart() {
+                // do nothing
+        }
+
+        public void onFinish() {
+                // do nothing
+        }
+
+        public void onRead(String s) {
+                log.debug(prefix + s);
+        }
+
+        public void onException(Throwable e) {
+                log.debug(prefix + "Exception");
+                log.debug(e);
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageInput.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.util.List;
+import java.util.ArrayList;
+import nsk.share.TestBug;
+
+public class StreamMessageInput implements MessageInput {
+        private Object sync = new Object();
+        private List<String> lines = new ArrayList<String>();
+        private int position = 0;
+        private volatile boolean active = false;
+        private volatile Throwable exception;
+
+        public StreamMessageInput() {
+        }
+
+        public StreamMessageInput(StreamReader sd) {
+                bind(sd);
+        }
+
+        public StreamListener createListener() {
+                return new Listener();
+        }
+
+        public void bind(StreamReader sd) {
+                sd.addListener(createListener());
+        }
+
+        public boolean isActive() {
+                return active;
+        }
+
+        public boolean isException() {
+                return exception != null;
+        }
+
+        public Throwable getException() {
+                return exception;
+        }
+
+        public boolean waitForStart(long timeout) throws InterruptedException {
+                long startTime = System.currentTimeMillis();
+                long curTime = startTime;
+                synchronized (sync) {
+                        while (!active && curTime - startTime < timeout) {
+                                sync.wait(curTime - startTime);
+                                curTime = System.currentTimeMillis();
+                        }
+                }
+                return active;
+        }
+
+        public boolean waitForFinish(long timeout) throws InterruptedException {
+                long startTime = System.currentTimeMillis();
+                long curTime = startTime;
+                synchronized (sync) {
+                        while (active && curTime - startTime < timeout) {
+                                sync.wait(curTime - startTime);
+                                curTime = System.currentTimeMillis();
+                        }
+                }
+                return !active;
+        }
+
+        public boolean waitForMessage(String msg, long timeout) throws InterruptedException {
+                long startTime = System.currentTimeMillis();
+                long curTime = startTime;
+                int n = position;
+                synchronized (sync) {
+                        while (curTime - startTime < timeout) {
+                                while (n < lines.size()) {
+                                        // System.out.println("Check: " + lines.get(n));
+                                        if (msg == null || lines.get(n++).contains(msg)) {
+                                                return true;
+                                        }
+                                }
+                                sync.wait(timeout - (curTime - startTime));
+                                curTime = System.currentTimeMillis();
+                        }
+                        return false;
+                }
+        }
+
+        public boolean waitForMessage(long timeout) throws InterruptedException {
+                return waitForMessage(null, timeout);
+        }
+
+        public String getMessage() {
+                if (position < lines.size())
+                        return lines.get(position++);
+                else
+                        return null;
+        }
+
+        public String getMessage(int index) {
+                return lines.get(index);
+        }
+
+        public int getPosition() {
+                return position;
+        }
+
+        public void setPosition(int position) {
+                this.position = position;
+        }
+
+        public int getMessageCount() {
+                return lines.size();
+        }
+
+        public List<String> getMessages() {
+                return getMessages(position, lines.size());
+        }
+
+        public List<String> getMessages(int to) {
+                return getMessages(position, to);
+        }
+
+        public List<String> getMessages(int from, int to) {
+                synchronized (sync) {
+                        if (to < 0)
+                                to = lines.size() + to;
+                        position = Math.max(position, to);
+                        return new ArrayList<String>(lines.subList(from, to));
+                }
+        }
+
+        public void reset() {
+                synchronized (sync) {
+                        position = lines.size();
+                }
+        }
+
+        private class Listener implements StreamListener {
+                @Override
+                public void onStart() {
+                        synchronized (sync) {
+                                active = true;
+                                sync.notifyAll();
+                        }
+                }
+
+                @Override
+                public void onRead(String line) {
+                        //System.out.println("onRead: " + line);
+                        synchronized (sync) {
+                                lines.add(line);
+                                sync.notifyAll();
+                        }
+                }
+
+                @Override
+                public void onFinish() {
+                        synchronized (sync) {
+                                active = false;
+                                sync.notifyAll();
+                        }
+                }
+
+                @Override
+                public void onException(Throwable e) {
+                        exception = e;
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamMessageOutput.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.IOException;
+import nsk.share.TestFailure;
+
+public class StreamMessageOutput implements MessageOutput {
+        private OutputStream out;
+        private PrintStream pout;
+
+        public StreamMessageOutput() {
+        }
+
+        public StreamMessageOutput(OutputStream out) {
+                bind(out);
+        }
+
+        public void bind(OutputStream out) {
+                this.out = out;
+                this.pout = new PrintStream(out, true); // Autoflush is important
+        }
+
+        public void start() {
+        }
+
+        public void send(String msg) {
+                pout.println(msg);
+        }
+
+        public void finish() {
+                pout.close();
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/process/StreamReader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.process;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+
+public class StreamReader extends Thread {
+        private InputStream in;
+        private List<StreamListener> listeners;
+        private volatile boolean terminate = false;
+        private static final long CLEANUP_TIMEOUT = 60000;
+
+        public StreamReader(String desc) {
+                super("Stream Reader: " + desc);
+                setDaemon(true);
+        }
+
+        public StreamReader(String desc, InputStream in) {
+                this(desc);
+                setStream(in);
+        }
+
+        public void setDescription(String desc) {
+                setName("Stream Reader: " + desc);
+        }
+
+        public void setStream(InputStream in) {
+                this.in = in;
+        }
+
+        public synchronized void addListener(StreamListener listener) {
+                if (listeners == null)
+                        listeners = new ArrayList<StreamListener>();
+                listeners.add(listener);
+        }
+
+        public synchronized void removeListener(StreamListener listener) {
+                if (listeners != null) {
+                        while (listeners.remove(listener))
+                                ;
+                }
+        }
+
+        public void run() {
+                onStart();
+                BufferedReader rd;
+                try {
+                        rd = new BufferedReader(new InputStreamReader(in));
+                        String line;
+                        while (!terminate) {
+                                line = rd.readLine();
+                                if (line == null)
+                                        break;
+                                onRead(line);
+                                while (rd.ready()) {
+                                        line = rd.readLine();
+                                        if (line == null)
+                                                break;
+                                        onRead(line);
+                                }
+                                if (line == null)
+                                        break;
+                        }
+                        cleanup();
+                        onFinish();
+                } catch (IOException e) {
+                        if (!terminate)
+                                onException(e);
+                        else
+                                onFinish();
+                }
+        }
+
+        protected void onStart() {
+                if (listeners != null) {
+                        for (StreamListener l : listeners)
+                                l.onStart();
+                }
+        }
+
+        protected void onRead(String line) {
+                //System.out.println("Read: " + line);
+                if (listeners != null) {
+                        for (StreamListener l : listeners)
+                                l.onRead(line);
+                }
+        }
+
+        protected void onFinish() {
+                if (listeners != null) {
+                        for (StreamListener l : listeners)
+                                l.onFinish();
+                }
+        }
+
+        protected void onException(Throwable e) {
+                if (listeners != null) {
+                        for (StreamListener l : listeners)
+                                l.onException(e);
+                }
+        }
+
+        private void cleanup() {
+                try {
+                        in.close();
+                } catch (IOException e) {
+                        e.printStackTrace();
+                }
+        }
+
+        public void kill() {
+                terminate = true;
+                try {
+                        this.join(CLEANUP_TIMEOUT);
+                } catch (InterruptedException e) {
+                        e.printStackTrace();
+                }
+                this.interrupt();
+                try {
+                        this.join(CLEANUP_TIMEOUT);
+                } catch (InterruptedException e) {
+                        e.printStackTrace();
+                }
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/stack/StackUtils.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.stack;
+
+import java.util.List;
+import java.util.Map;
+
+import nsk.share.TestFailure;
+import nsk.share.log.Log;
+
+public final class StackUtils {
+        private StackUtils() {
+        }
+
+        private static String replace(String s) {
+                return (s == null || s.length() == 0) ? "?" : s;
+        }
+
+        /**
+         * String representation of stack trace element.
+         *
+         * Note that null and empty values are replaced with '?'.
+         */
+        public static String strStackTraceElement(StackTraceElement element) {
+                return "at " + replace(element.getClassName()) + "." + replace(element.getMethodName()) + "(" + replace(element.getFileName()) + ":" + element.getLineNumber() + ")";
+        }
+
+        public static void printStackTraceElement(Log log, StackTraceElement element) {
+                log.info("       " + strStackTraceElement(element));
+        }
+
+        public static void printStackTrace(Log log, StackTraceElement[] elements) {
+                for (StackTraceElement element : elements)
+                        printStackTraceElement(log, element);
+        }
+
+        public static void printStackTrace(Log log, Iterable<StackTraceElement> elements) {
+                for (StackTraceElement element : elements)
+                        printStackTraceElement(log, element);
+        }
+
+        /**
+         * Check that element matches expected element.
+         *
+         * Expected element is used as pattern for matching. A null or empty
+         * field value means that no comparison is done.
+         */
+        public static boolean matches(StackTraceElement element, StackTraceElement expected) {
+                return
+                        (expected.getClassName() == null || expected.getClassName().length() == 0 || expected.getClassName().equals(element.getClassName())) &&
+                        (expected.getMethodName() == null || expected.getMethodName().length() == 0 || expected.getMethodName().equals(element.getMethodName())) &&
+                        (expected.isNativeMethod() == element.isNativeMethod());
+        }
+
+        public static StackTraceElement expectedTraceElement(String className, String methodName, boolean nativeMethod) {
+                // Replace null className with empty because StackTraceElement constructor does not allow null className.
+                return new StackTraceElement(className == null ? "" : className, methodName, null, (nativeMethod ? -2 : 0));
+        }
+
+        public static void addExpectedTraceElement(List<StackTraceElement> expectedTrace, String className, String methodName, boolean nativeMethod) {
+                expectedTrace.add(0, expectedTraceElement(className, methodName, nativeMethod));
+        }
+
+        /**
+         * Check that trace elements starting from given index match expected elements.
+         */
+        public static void checkMatches(StackTraceElement[] elements, List<StackTraceElement> expectedTrace, int i) {
+                if (elements.length - i < expectedTrace.size())
+                        throw new TestFailure("Expected at least " + expectedTrace.size() + " trace elements, got only " + (i + 1));
+                for (int j = 0; j < expectedTrace.size(); ++j) {
+                        StackTraceElement expected = expectedTrace.get((expectedTrace.size() - 1) - j);
+                        int index = (elements.length - 1) - i - j;
+                        StackTraceElement actual = elements[index];
+                        if (!matches(actual, expected))
+                                throw new TestFailure("Expected element at index " + index + " to match: " + strStackTraceElement(expected));
+                }
+        }
+
+        /**
+         * Find matching stack trace element starting from top of the stack.
+         */
+        public static int findMatch(StackTraceElement[] elements, StackTraceElement expected) {
+                for (int i = 0; i < elements.length; ++i)
+                        if (StackUtils.matches(elements[elements.length - 1 - i], expected))
+                                return i;
+                return -1;
+        }
+
+        /**
+         * Find the stack trace element that contains the "main(String[])" method
+         *
+         * @return StackTraceElement containing "main" function, null if there are more than one
+         */
+        public static StackTraceElement findMain() {
+                Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
+                StackTraceElement mainMethodFrame = null;
+                for(StackTraceElement[] current : stackTraces.values()) {
+                        if (current.length > 0) {
+                                StackTraceElement last = current[current.length - 1];
+                                if ("main".equals(last.getMethodName())) {
+                                        if (mainMethodFrame == null) {
+                                                mainMethodFrame = last;
+                                        } else if (!mainMethodFrame.getClassName().equals(last.getClassName())) {
+                                                // more than one class has a "main"
+                                                return null;
+                                        }
+                                }
+                        }
+                }
+                return mainMethodFrame;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/transform/AbstractClassFileTransformer.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.transform;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+
+public abstract class AbstractClassFileTransformer
+        implements ClassFileTransformer {
+    protected abstract boolean shouldBeTransformed(String name);
+
+    protected abstract byte[] transformClass(byte[] bytes);
+
+    @Override
+    public byte[] transform(ClassLoader loader, String className,
+            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
+            byte[] classfileBuffer) throws IllegalClassFormatException {
+        if (shouldBeTransformed(className)) {
+            return transformClass(classfileBuffer);
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/transform/AnnotationAppender.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.transform;
+
+import jdk.internal.org.objectweb.asm.AnnotationVisitor;
+
+public abstract class AnnotationAppender {
+    private final String desc;
+    private final boolean visible;
+    private boolean annotationPresent;
+
+    public AnnotationAppender(String desc, boolean visible) {
+        this.desc = desc;
+        this.visible = visible;
+    }
+
+    public void checkAnnotation(String desc, boolean isVisible) {
+        annotationPresent |= visible == isVisible && this.desc.equals(desc);
+    }
+
+    public void addAnnotation(VisitAnnotation func) {
+        if (shouldAdd()) {
+            AnnotationVisitor av = func.visit(desc, true);
+            if (av != null) {
+                postCreate(av);
+                av.visitEnd();
+                annotationPresent = true;
+            }
+        }
+    }
+
+    protected boolean shouldAdd() {
+        return !annotationPresent;
+    }
+
+    protected abstract void postCreate(AnnotationVisitor av);
+
+    @FunctionalInterface
+    public static interface VisitAnnotation {
+        AnnotationVisitor visit(String desc, boolean visible);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/transform/TransformingClassLoader.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.transform;
+
+import vm.share.FileUtils;
+
+public class TransformingClassLoader extends ClassLoader {
+    private final AbstractClassFileTransformer transformer;
+
+    protected TransformingClassLoader(ClassLoader parent,
+            AbstractClassFileTransformer transformer) {
+        super(parent);
+        this.transformer = transformer;
+    }
+
+    @Override
+    protected Class<?> loadClass(String name, boolean resolve)
+            throws ClassNotFoundException {
+        if (!transformer.shouldBeTransformed(name)) {
+            return super.loadClass(name, resolve);
+        }
+        synchronized (getClassLoadingLock(name)) {
+            // First, check if the class has already been loaded
+            Class<?> c = findLoadedClass(name);
+            if (c == null) {
+                try {
+                    byte[] bytes = FileUtils.readClass(name);
+                    bytes = transformer.transformClass(bytes);
+                    c = defineClass(name, bytes, 0, bytes.length);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    return super.loadClass(name, resolve);
+                }
+            }
+            if (resolve) {
+                resolveClass(c);
+            }
+            return c;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/Crasher.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmcrasher;
+
+public abstract class Crasher implements Runnable {
+
+    public abstract void run();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/CrasherFactory.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmcrasher;
+
+import vm.share.options.BasicOptionObjectFactory;
+import vm.share.options.FClass;
+import vm.share.options.Factory;
+
+@Factory(placeholder_text="Crasher type", default_value="signal", classlist={
+        @FClass(key="signal", description="Crash VM with a signal", type=SignalCrasher.class),
+        @FClass(key="unsafe.gc", description="Crash VM in GC with Unsafe interface", type=UnsafeGCCrasher.class),
+        @FClass(key="unsafe.java", description="Crash VM in Java thread with Unsafe interface", type=UnsafeJavaCrasher.class),
+})
+public class CrasherFactory extends BasicOptionObjectFactory<Runnable> {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/SignalCrasher.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmcrasher;
+
+import vm.share.ProcessUtils;
+import vm.share.options.Option;
+
+public class SignalCrasher extends Crasher {
+    @Option(name="signalnum", description="signal number", default_value="2")
+    private int num;
+
+    public void run() {
+        ProcessUtils.sendSignal(num);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/UnsafeGCCrasher.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmcrasher;
+
+import vm.share.UnsafeAccess;
+
+public class UnsafeGCCrasher extends Crasher {
+
+    private static class C {
+        C next;
+    }
+
+    private static C a = null;
+
+    @SuppressWarnings("restriction")
+    @Override
+    public void run() {
+        try {
+            a = new C();
+            a.next = new C();
+            a.next.next = new C();
+            a.next.next.next = new C();
+            UnsafeAccess.unsafe.putInt(a.next, UnsafeAccess.unsafe.objectFieldOffset(C.class.getDeclaredField("next")), 0xDEADCAFE);
+            System.gc();
+            Thread.sleep(1000);
+        } catch ( Throwable t ) {
+            t.printStackTrace();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmcrasher/UnsafeJavaCrasher.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmcrasher;
+
+import vm.share.UnsafeAccess;
+
+public class UnsafeJavaCrasher extends Crasher {
+
+    private static class C {
+        C next;
+    }
+
+    @SuppressWarnings("restriction")
+    @Override
+    public void run() {
+        try {
+            C a = new C();
+            a.next = new C();
+            a.next.next = new C();
+            UnsafeAccess.unsafe.putInt(a.next, UnsafeAccess.unsafe.objectFieldOffset(C.class.getDeclaredField("next")), 0xDEADCAFE);
+            a.next.next.next = new C();
+        } catch ( Throwable t ) {
+            t.printStackTrace();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/CompileAndDeoptimize.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmstresser;
+
+public class CompileAndDeoptimize implements Runnable {
+
+    public static int v = 0;
+
+    private abstract static class A {
+        public abstract void incv();
+    }
+
+    private static class B extends A {
+        public void incv() {
+            v++;
+        }
+    }
+
+    public static class C extends A {
+        public void incv() {
+            v += (new int[1][1][1][1][1][1][1][1]).length;
+        }
+    }
+
+    private volatile boolean done = false;
+    public volatile A a = new B();
+
+    private void incv() {
+        a.incv();
+    }
+
+    private void inc() {
+        while ( ! done ) {
+            incv();
+        }
+        //while ( ! done ) {
+        //      incv();
+        //}
+        //while ( ! done ) {
+        //      incv();
+        //}
+    }
+
+    public void run() {
+        try {
+            Thread t = new Thread(new Runnable() { @Override public void run() { inc(); } });
+            t.start();
+            Thread.sleep(100);
+            a = (A) CompileAndDeoptimize.class.getClassLoader().loadClass(B.class.getName().replaceAll("B$", "C")).getConstructors()[0].newInstance(new Object[0]);
+            //Thread.sleep(1000);
+            //done = true;
+            //t.join();
+
+        } catch ( Throwable t ) {
+            t.printStackTrace();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/vmTestbase/vm/share/vmstresser/MetaspaceStresser.java	Mon Apr 30 18:10:24 2018 -0700
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package vm.share.vmstresser;
+
+import java.util.*;
+import java.util.concurrent.locks.*;
+
+import nsk.share.*;
+import nsk.share.classload.*;
+import nsk.share.test.*;
+
+/**
+ * Stresser that load classes until OOME, then unload some of them and continue loading.
+ */
+public class MetaspaceStresser extends Thread {
+
+    /**
+     * Capacity of class containers.
+     * This amount of classes will be unloaded on reset call.
+     */
+    public static final int DEFAULT_BUCKET_SIZE = 4000;
+
+    public static final int DEFAULT_PAUSE_TIME = 0;
+
+    /*
+     * Loaded classes stored in ClassContainer instances.
+     * Such instances organized in array-based stack as it is
+     * one of the simplest way to minimize possibility
+     * to get OOME and guarntee that after replacing
+     * reference to class container by null there will be
+     * no cached refereces and container will be reclaimed by
+     * GC and classes will become unloadable.
+     */
+    // Maximum available amount of arrays with class containers.
+    private static final int CONTAINERS_ARRAY_LENGTH = 1000;
+    // Maximum length array with class containers.
+    private static final int CONTAINER_ARRAYS_COUNT = 100;
+
+    private ClassContainersStack containersStack = new ClassContainersStack(CONTAINER_ARRAYS_COUNT * CONTAINERS_ARRAY_LENGTH,
+            CONTAINERS_ARRAY_LENGTH);
+    private ClassContainer newContainer = null;
+
+    private ExecutionController controller = null;
+    private int bucketSize = DEFAULT_BUCKET_SIZE;
+    private int pauseTime = DEFAULT_PAUSE_TIME;
+
+    private ReentrantLock lock = new ReentrantLock();
+
+    /**
+     * Construct MetaspaceStrresser with default bucket size
+     * and pause time.
+     * @param c controller to control execution time.
+     */
+    public MetaspaceStresser(ExecutionController c) {
+        controller = c;
+    }
+
+    /**
+     * Construct MetaspaceStrresser with custom bucket size
+     * and pause time.
+     * @param c controller to control execution time.
+     * @param bucketSize classes to be unloaded on reset.
+     * @param pauseTime pause after reset.
+     */
+    public MetaspaceStresser(ExecutionController c, int bucketSize, int pauseTime) {
+        this(c);
+        this.bucketSize = bucketSize;
+        this.pauseTime = pauseTime;
+    }
+
+    /**
+     *  Fill Metaspace with classes.
+     *  Classes will be loaded until OOME, then some of them will be unloaded.
+     */
+    public synchronized void prepare() {
+        while (controller.continueExecution()) {
+            try {
+                fillContainerStack();
+            } catch (OutOfMemoryError oome) {
+                unloadLastClassBucket();
+                return;
+            } catch (ClassNotFoundException cnfe) {
+                throw new TestBug("Unexpected exception in stresser.", cnfe);
+            }
+        }
+    }
+
+    /**
+     * Load new class to container, fill containerStack.
+     * Classes will be loaded until OOME
+     * @throws ClassNotFoundException
+     */
+    private void fillContainerStack() throws ClassNotFoundException {
+        newContainer = new ClassContainer();
+        while (newContainer.size() < bucketSize && controller.continueExecution()) {
+            newContainer.loadClass();
+        }
+        containersStack.push(newContainer);
+        newContainer = null;
+    }
+
+    /**
+     * Run stresser.
+     * Stresser will load classes until OOME, then bucketSize classes
+     * will be unloaded and stresser will wait pauseTime millisiconds
+     * before continuing class loading.
+     */
+    public void run() {
+        try {
+            while (controller.continueExecution()) {
+                try {
+                    fillContainerStack();
+                } catch (OutOfMemoryError oome) {
+                    unloadLastClassBucket();
+                    try {
+                        Thread.sleep(pauseTime);
+                    } catch (InterruptedException ie) {
+                    }
+                }
+            }
+        } catch (Throwable e) {
+            throw new TestBug("Unexpected exception in stresser.", e);
+        } finally {
+            containersStack.free();
+        }
+    }
+
+    /**
+     * Unload most recently loaded bucket of classes.
+     */
+    public void unloadLastClassBucket() {
+        while (controller.continueExecution()) {
+            try {
+                containersStack.pop();
+                System.gc();
+                break;
+            } catch (OutOfMemoryError oome) {
+                oome.printStackTrace();
+                continue;
+            }
+        }
+    }
+
+    /**
+     * Array-based stack for ClassContainer's.
+     */
+    private class ClassContainersStack {
+
+        private int arrayLength = 0;
+        private int arraysCount = 0;
+        private int arrayIndex = 0;
+        private int elemIndex = 0;
+
+        private ClassContainer data[][];
+
+        /**
+         * Create ClassContainersStack that will be able
+         * to store size classes in arrays of segmentSize length.
+         */
+        public ClassContainersStack(int size, int segementSize) {
+            arrayLength = segementSize;
+            arraysCount = size / arrayLength;
+            data = new ClassContainer[arraysCount][];
+            data[0] = new ClassContainer[arrayLength];
+        }
+
+        /**
+         * Push ClassContainer c into stack.
+         */
+        public synchronized void push(ClassContainer c) {
+            data[arrayIndex][elemIndex] = c;
+            elemIndex++;
+            if (elemIndex == arrayLength) {
+                if (arrayIndex == arraysCount) {
+                    throw new TestBug("ClassContainersStack ran out of available slots");
+                }
+                data[arrayIndex + 1] = new ClassContainer[arrayLength];
+                arrayIndex++;
+                elemIndex = 0;
+            }
+        }
+
+        /**
+         * Remove reference to top ClassContainer.
+         */
+        public synchronized void pop() {
+            data[arrayIndex][elemIndex] = null;
+            if (elemIndex > 0) {
+                elemIndex--;
+            } else if (arrayIndex > 0) {
+                data[arrayIndex] = null;
+                arrayIndex--;
+                elemIndex = arrayLength - 1;
+            }
+        }
+
+        /**
+         * Remove all stored ClassContainers.
+         */
+        public synchronized void free() {
+            data = null;
+            System.gc();
+            data = new ClassContainer[arraysCount][];
+            data[0] = new ClassContainer[arrayLength];
+            arrayIndex = 0;
+            elemIndex = 0;
+        }
+
+    }
+
+    /// Variable used to create uniqe name for generated classes.
+    private static long lastClass = 0;
+
+    /**
+     * Class container consists of classes and their ClassLoader, so
+     * if there will be no references to container and classes inside it then
+     * it could be easely collected by GC.
+     */
+    private class ClassContainer {
+
+        private List<Class> classes = new LinkedList<Class>();
+        private GeneratingClassLoader loader = new GeneratingClassLoader();
+        private String prefix = loader.getPrefix();
+        private int length = loader.getNameLength();
+
+        public void loadClass() throws ClassNotFoundException {
+            String newName = prefix + "c" + lastClass;
+            lastClass++;
+            while (newName.length() < length) {
+                newName = newName + "c";
+            }
+            classes.add(loader.loadClass(newName));
+        }
+
+        public int size() {
+            return classes.size();
+        }
+    }
+
+}