diff -r 5b3afcfc9926 test/JtregNativeHotspot.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/JtregNativeHotspot.gmk Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,1547 @@ +# +# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +################################################################################ +# This file builds the native component of the JTReg tests for Hotspot. +# It also covers the test-image part, where the built files are copied to the +# test image. +################################################################################ + +default: all + +include $(SPEC) +include MakeBase.gmk +include TestFilesCompilation.gmk + +################################################################################ +# Targets for building the native tests themselves. +################################################################################ + +# This might have been added to by a custom extension. +BUILD_HOTSPOT_JTREG_NATIVE_SRC += $(TOPDIR)/hotspot/test + +BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(ALT_OUTPUTDIR)/support/test/hotspot/jtreg/native + +################################################################################ +# Former VM TestBase tests. +################################################################################ + +VM_TESTBASE_DIR := $(TOPDIR)/hotspot/test/vmTestbase + +VM_SHARE_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/vm/share \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_MONITORING_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_JDI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native + +NSK_SHARE_JDI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jdi + +NSK_SHARE_JNI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +RUNTIME_DEFMETH_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti + +NSK_SHARE_LOCKS_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/locks + +MLVM_JVMTI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti/agent_common \ + -I$(VM_TESTBASE_DIR)/vm/mlvm/share + +MLVM_STRESS_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_GC_LOCK_JVMTI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/gc/lock/jvmti \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_GC_LOCK_MALLOC_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/gc/lock/malloc \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_GC_LOCK_JNI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/gc/lock/jni \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_GC_LOCK_REF_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/gc/lock/jniref \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_STRACE_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NSK_STRESS_JNI_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/stress/jni + +NSK_JVMTI_AGENT_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti/agent_common + +NSK_JVMTI_AOD_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/aod \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti \ + -I$(VM_TESTBASE_DIR)/nsk/share/jvmti/aod + +NSK_AOD_INCLUDES := \ + -I$(VM_TESTBASE_DIR)/nsk/share/aod \ + -I$(VM_TESTBASE_DIR)/nsk/share/native \ + -I$(VM_TESTBASE_DIR)/nsk/share/jni + +NO_FRAMEPOINTER_CFLAGS := +ifeq ($(call isTargetOs, linux), true) + NO_FRAMEPOINTER_CFLAGS := -fomit-frame-pointer +endif + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libNoFramePointer := $(NO_FRAMEPOINTER_CFLAGS) +# Optimization -O3 needed, HIGH == -O3 +BUILD_HOTSPOT_JTREG_LIBRARIES_OPTIMIZATION_libNoFramePointer := HIGH + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS +BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS := -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libProcessUtils := $(VM_SHARE_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libThreadController := $(NSK_MONITORING_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libDeadlock := $(NSK_MONITORING_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libRecursiveMonitoringThread := $(NSK_MONITORING_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libLockingThreads := $(NSK_MONITORING_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libStackTraceController := $(NSK_MONITORING_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefineClasses := $(RUNTIME_DEFMETH_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libforceEarlyReturn005a := $(NSK_JDI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libMonitorEnterExecutor := $(NSK_SHARE_JDI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIreferences := $(NSK_SHARE_JNI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libLockingThread := $(NSK_SHARE_LOCKS_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIMonitorLocker := $(NSK_SHARE_LOCKS_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstepBreakPopReturn := $(MLVM_JVMTI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libIndyRedefineClass := $(MLVM_JVMTI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnativeAndMH := $(MLVM_STRESS_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJVMTIAllocLocker := $(NSK_GC_LOCK_JVMTI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libMallocLocker := $(NSK_GC_LOCK_MALLOC_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libBooleanArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libByteArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libCharArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libDoubleArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libFloatArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libIntArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libLongArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libShortArrayCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libStringCriticalLocker := $(NSK_GC_LOCK_JNI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIGlobalRefLocker := $(NSK_GC_LOCK_REF_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNILocalRefLocker := $(NSK_GC_LOCK_REF_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIRefLocker := $(NSK_GC_LOCK_REF_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libJNIWeakGlobalRefLocker := $(NSK_GC_LOCK_REF_INCLUDES) + + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace003 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace004 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace005 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace006 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace008 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace009 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace011 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace012 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace014 := $(NSK_STRACE_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstrace015 := $(NSK_STRACE_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcl001 := $(NSK_STRESS_JNI_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbootclssearch_agent := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsystemclssearch_agent := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsysprop001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsysprop002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetlocal001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetlocal002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libGetEnv001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetvern001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldecl002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldecl004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldecl001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libloadedclss001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libloadedclss002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libextevents001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdatadumpreq001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtimerinfo001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrstat002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrstat005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrstat004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrstat003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrstat001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframecnt001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframecnt002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframecnt003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcontmon003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcontmon002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcontmon001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrtimerinfo001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetenvstor001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetenvstor002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetenvstor003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframeloc002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframeloc003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframeloc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass031 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass030 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass015 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass012 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass024 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass023 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass022 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass025 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass013 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass014 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstressRedefine := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass011 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass029 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass016 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass020 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass018 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass027 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass019 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass026 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass021 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass028 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass017 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefclass010 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetjlocfmt002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetjlocfmt001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetlocal003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetlocal004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetallstktr001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetcpool001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libextmech := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentthr := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libheapref := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librefignore := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libIsSyntheticIssynth001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblinetab004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgc := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonitor := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfollowref001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclsldrclss00x := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretvoid := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretlong := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretint := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretbase := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretstr := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretobj := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libearlyretfp := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetavailproc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclstat006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclstat007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclstat005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrinfo002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrinfo001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetthrdstor002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetthrdstor003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetthrdstor001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjsize001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libaddcaps001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libaddcaps002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libaddcaps003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmthd007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmthd006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmthd005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldacc003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldacc004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldacc002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldacc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsrcfn006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsrcfn005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsrcfn004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetthrdstor001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libintrpthrd001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libintrpthrd002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libintrpthrd003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnativemethbind002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnativemethbind004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnativemethbind003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnativemethbind001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetenvstor001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetextevent001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetpotcaps001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterobjreachobj001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterobjreachobj002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterobjreachobj005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterobjreachobj004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterobjreachobj003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrfldw002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrfldw001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libvminit001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrd003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdeclcls001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetjniftab002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetjniftab001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgeterrname002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgeterrname001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsettag001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstopthrd007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libstopthrd006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgenevents001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldmdf004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldmdf003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresumethrdlst001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresumethrdlst002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetbrk008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetbrk007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetbrk005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetbrk002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetbrk003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrdlst001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsuspendthrdlst002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libIsMethodSyntheticIssynth001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libissynth002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentonunload001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetsysprop002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetsysprop003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgettag001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnframepop001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnframepop003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnframepop002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libvmobjalloc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjwithtags001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfy004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfy003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfy002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfy001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethmod001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethmod002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmentry002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmentry001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterheap001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe010 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe011 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libpopframe007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcurthrtimerinfo001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnwait004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnwait003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnwait002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnwait005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnwait001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfldw002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrfmodw001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrfmodw002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisnative002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisnative001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterreachobj002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterreachobj005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterreachobj004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterreachobj003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterreachobj001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liballthr001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liballthr002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjhashcode001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdyncodgen001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetnotif001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmexit001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmexit002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethloc002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethloc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbreakpoint001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetcaps001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetcaps002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclsldrclss001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclsldrclss002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblinetab001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblinetab003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblinetab002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmaxloc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmaxloc002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassfloadhk009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetintrf006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetintrf007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetintrf005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexcatch001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresumethrd002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresumethrd001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjfree001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjfree002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldmod002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libfieldmod001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libextfuncs001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libSetNativeMethodPrefix002Main := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libSetNativeMethodPrefix002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libSetNativeMethodPrefix001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassprep001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetvrbflag002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetvrbflag001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmcontentered001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetevntcallb001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetevntcallb002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetevntcallb003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfyall002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfyall004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfyall003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmnntfyall001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcfinish001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libownmoninf002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libownmoninf003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libownmoninf001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldnm003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldnm004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetfldnm005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf08t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf08t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf08t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgf04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi02t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi03t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi04t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi01t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbi01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libex03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t013 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t014 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t015 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t012 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t019 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t021 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t017 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t010 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t011 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t016 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t020 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t018 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcm01t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp02t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp02t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp05t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp05t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp04t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp03t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp06t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp06t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp01t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp01t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp07t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsp07t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc03t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc05t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtc01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma08t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma08t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma01t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma06t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma07t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma07t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma05t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma05t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma02t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma03t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t003a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t002a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t003a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t004a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t005a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t002a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t007a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t008a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t001a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libma10t006a := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs103t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs104t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs104t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs301t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs301t005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs301t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs301t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs301t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs203t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs203t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs203t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs203t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs204t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs204t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs204t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs204t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs202t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs202t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t011 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t010 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs302t012 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs201t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs201t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libhs201t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem01t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem07t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem07t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t012 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t010 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem02t011 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem05t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem05t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libem04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji03t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji03t004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji03t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libji05t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap10t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap11t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap02t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap05t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap05t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap04t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap04t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap04t003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap03t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap12t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap06t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap01t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap09t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap07t001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libap07t002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthreadstart001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthreadstart003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthreadstart002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonenter002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonenter003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonenter004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonenter001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdealloc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisfldsin003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisfldsin002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrgrpinfo001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrgrpinfo002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libAbort := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libCallbacks := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libNonConcreteKlassFilter := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libConcreteKlassFilter := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libHeapFilter := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmcontenter001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrbrk001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrbrk002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclrbrk005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtopthrgrp002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtopthrgrp001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisarray004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisarray005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbytecodes003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbytecodes002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libbytecodes001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthreadend001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthreadend002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetthrdgrpchld001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmonitorwait001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liballoc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsrcdebugex003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsrcdebugex002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsrcdebugex001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcrrawmon002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcrrawmon001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetjniftab001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetjniftab002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsldr003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsldr002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsldr001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcurthrcputime001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonexit001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonexit002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonexit005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librawmonexit003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisobsolete001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libargsize001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libargsize002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclfld007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclfld006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclfld005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr008 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr009 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetstacktr003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblocaltab001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblocaltab004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblocaltab003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblocaltab002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_liblocaltab005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libclassload001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisintrf004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libisintrf005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframepop001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libframepop002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsig005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsig004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclsig006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdisposeenv001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexception001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libexceptionjni001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libresexhausted := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgcstart002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libiterinstcls007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethname002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethname003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmethname001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libforcegc001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libforcegc002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgettime001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libobjmonusage001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentonload001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentonload002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentonload003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrcputime002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libthrcputime001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libmonitorwaited001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libForceEarlyReturn001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentthr003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentthr002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libagentthr001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcompmethunload001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libretransform002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libretransform004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libretransform003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmdf007 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmdf006 :=$(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmdf004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetclmdf005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetlocal001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetlocal004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetlocal003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetlocal002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libcompmethload001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsysprops001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetsysprops002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdrrawmon003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdrrawmon004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libdrrawmon001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsinglestep001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsinglestep003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsinglestep002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librelcaps001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_librelcaps002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw004 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw003 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw005 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw006 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetfmodw001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libvmdeath001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetphase001 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libgetphase002 := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libMethodBind := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libOnUnload := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libStackTrace := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libredefineCFLH := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libAddToBootstrapClassLoaderSearch := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libDispose := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libenvironment := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnosuspendMonitorInfo := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libnosuspendStackTrace := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsetNullVMInit := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libtimers := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libHeap := $(NSK_JVMTI_AGENT_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libHotSwap := $(NSK_JVMTI_AGENT_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach046Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach041Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach015Agent01 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach015Target := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach015Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach012Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach040Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach014Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach022Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach038Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach009Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libsimpleAgent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach037Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach008Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach039Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach020Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach042Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach045Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach045Agent03 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach045Agent02 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach045Agent01 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach002aAgent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach021Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach050Agent00 := $(NSK_JVMTI_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libattach002Agent00 := $(NSK_JVMTI_AOD_INCLUDES) + +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent00 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent01 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent02 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine07agent03 := $(NSK_AOD_INCLUDES) +BUILD_HOTSPOT_JTREG_LIBRARIES_CFLAGS_libVirtualMachine09agent00 := $(NSK_AOD_INCLUDES) + +################################################################################ + +# Platform specific setup +ifeq ($(call And, $(call isTargetOs, solaris) $(call isTargetCpuArch, sparc)), false) + BUILD_HOTSPOT_JTREG_EXCLUDE += liboverflow.c exeThreadSignalMask.c +endif + +ifeq ($(call isTargetOs, linux), true) + BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libtest-rw := -z noexecstack + BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libtest-rwx := -z execstack + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libstepBreakPopReturn := -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIndyRedefineClass := -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefineClasses := -pthread + BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeinvoke := -ljvm -pthread + BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exestack-gap := -ljvm -pthread + BUILD_TEST_exeinvoke_exeinvoke.c_OPTIMIZATION := NONE + BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exeFPRegs := -ldl +else + BUILD_HOTSPOT_JTREG_EXCLUDE += libtest-rw.c libtest-rwx.c libTestJNI.c \ + exeinvoke.c exestack-gap.c +endif + +BUILD_HOTSPOT_JTREG_EXECUTABLES_LIBS_exesigtest := -ljvm + +ifeq ($(call isTargetOs, solaris), true) + BUILD_HOTSPOT_JTREG_EXCLUDE += libterminatedThread.c +endif + +ifeq ($(call isTargetOs, windows), true) + BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT + BUILD_HOTSPOT_JTREG_EXCLUDE += exesigtest.c libterminatedThread.c + +else + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbootclssearch_agent += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsystemclssearch_agent += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsysprop001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsysprop002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetlocal001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetlocal002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetEnv001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetvern001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldecl002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldecl004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldecl001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libloadedclss001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libloadedclss002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libextevents001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdatadumpreq001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtimerinfo001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrstat002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrstat005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrstat004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrstat003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrstat001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframecnt001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframecnt002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframecnt003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcontmon003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcontmon002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcontmon001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrtimerinfo001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetenvstor001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetenvstor002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetenvstor003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframeloc002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframeloc003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframeloc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass031 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass030 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass015 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass012 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass024 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass023 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass022 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass025 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass013 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass014 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libstressRedefine += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass011 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass029 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass016 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass020 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass018 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass027 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass019 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass026 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass021 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass028 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass017 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefclass010 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetjlocfmt002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetjlocfmt001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetlocal003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetlocal004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetallstktr001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetcpool001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libextmech += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentthr += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libheapref += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librefignore += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIsSyntheticIssynth001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblinetab004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgc += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonitor += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfollowref001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclsldrclss00x += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretvoid += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretlong += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretint += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretbase += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretstr += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretobj += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libearlyretfp += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetavailproc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclstat006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclstat007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclstat005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrinfo002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrinfo001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetthrdstor002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetthrdstor003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetthrdstor001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjsize001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libaddcaps001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libaddcaps002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libaddcaps003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmthd007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmthd006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmthd005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldacc003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldacc004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldacc002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldacc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsrcfn006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsrcfn005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsrcfn004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetthrdstor001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libintrpthrd001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libintrpthrd002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libintrpthrd003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativemethbind002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativemethbind004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativemethbind003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnativemethbind001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetenvstor001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetextevent001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetpotcaps001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterobjreachobj001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterobjreachobj002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterobjreachobj005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterobjreachobj004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterobjreachobj003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrfldw002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrfldw001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libvminit001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrd003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdeclcls001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetjniftab002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetjniftab001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgeterrname002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgeterrname001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsettag001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libstopthrd007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libstopthrd006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgenevents001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldmdf004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldmdf003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libresumethrdlst001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libresumethrdlst002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetbrk008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetbrk007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetbrk005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetbrk002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetbrk003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrdlst001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsuspendthrdlst002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIsMethodSyntheticIssynth001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libissynth002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentonunload001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetsysprop002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetsysprop003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMethodBind += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libOnUnload += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libStackTrace += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libredefineCFLH += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAddToBootstrapClassLoaderSearch += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libDispose += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libenvironment += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnosuspendMonitorInfo += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnosuspendStackTrace += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetNullVMInit += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtimers += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHeap += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHotSwap += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach046Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach041Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach015Agent01 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach015Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach015Target += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach012Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach040Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach014Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach022Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach038Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach009Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsimpleAgent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach037Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach008Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach039Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach020Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach042Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach045Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach045Agent03 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach045Agent02 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach045Agent01 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach002aAgent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach021Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach050Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libattach002Agent00 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgettag001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnframepop001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnframepop003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libnframepop002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libvmobjalloc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjwithtags001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfy004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfy003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfy002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfy001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethmod001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethmod002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmentry002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmentry001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterheap001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe010 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe011 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libpopframe007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcurthrtimerinfo001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnwait004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnwait003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnwait002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnwait005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnwait001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfldw002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrfmodw001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrfmodw002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisnative002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisnative001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterreachobj002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterreachobj005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterreachobj004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterreachobj003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterreachobj001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liballthr001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liballthr002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjhashcode001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdyncodgen001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetnotif001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmexit001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmexit002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethloc002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethloc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbreakpoint001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetcaps001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetcaps002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclsldrclss001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclsldrclss002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblinetab001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblinetab003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblinetab002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmaxloc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmaxloc002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassfloadhk009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetintrf006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetintrf007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetintrf005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libexcatch001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libresumethrd002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libresumethrd001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjfree001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjfree002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldmod002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libfieldmod001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libextfuncs001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSetNativeMethodPrefix002Main += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSetNativeMethodPrefix002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSetNativeMethodPrefix001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassprep001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetvrbflag002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetvrbflag001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmcontentered001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetevntcallb001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetevntcallb002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetevntcallb003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfyall002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfyall004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfyall003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmnntfyall001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgcfinish001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libownmoninf002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libownmoninf003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libownmoninf001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldnm003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldnm004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetfldnm005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf08t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf08t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf08t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgf04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi02t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi03t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi04t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi01t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbi01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libex03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t013 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t014 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t015 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t012 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t019 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t021 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t017 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t010 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t011 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t016 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t020 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t018 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcm01t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp02t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp02t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp05t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp05t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp04t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp03t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp06t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp06t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp01t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp01t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp07t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsp07t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc03t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc05t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtc01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma08t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma08t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma01t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma06t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma07t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma07t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma05t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma05t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma02t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma03t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t003a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t002a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t003a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t004a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t005a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t002a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t007a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t008a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t001a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libma10t006a += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs103t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs104t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs104t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs301t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs301t005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs301t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs301t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs301t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs203t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs203t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs203t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs203t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs204t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs204t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs204t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs204t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs202t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs202t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_build += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t011 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t010 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs302t012 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs201t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs201t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libhs201t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem01t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem07t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem07t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t012 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t010 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem02t011 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem05t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem05t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libem04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji03t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji03t004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji03t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libji05t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap10t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap11t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap02t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap05t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap05t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap04t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap04t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap04t003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap03t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap12t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap06t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap01t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap09t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap07t001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libap07t002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthreadstart001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthreadstart003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthreadstart002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonenter001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdealloc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libexceptionjni001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisfldsin002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrgrpinfo001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrgrpinfo002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAbort += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libCallbacks += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libNonConcreteKlassFilter += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libConcreteKlassFilter += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libHeapFilter += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmcontenter001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrbrk001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrbrk002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclrbrk005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtopthrgrp002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libtopthrgrp001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisarray004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisarray005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbytecodes003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbytecodes002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libbytecodes001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthreadend001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthreadend002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetthrdgrpchld001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmonitorwait001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liballoc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsrcdebugex003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsrcdebugex002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsrcdebugex001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcrrawmon002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcrrawmon001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetjniftab001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetjniftab002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsldr003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsldr002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsldr001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcurthrcputime001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonexit001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonexit002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonexit005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librawmonexit003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisobsolete001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libargsize001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libargsize002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclfld007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclfld006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclfld005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr008 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr009 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetstacktr003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblocaltab001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblocaltab004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblocaltab003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblocaltab002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liblocaltab005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libclassload001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisintrf004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libisintrf005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframepop001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libframepop002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsig005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsig004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclsig006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdisposeenv002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdisposeenv001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libexception001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libresexhausted += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgcstart001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgcstart002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libiterinstcls007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethname002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethname003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmethname001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libforcegc001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libforcegc002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgettime001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libobjmonusage001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentonload001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentonload002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentonload003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrcputime002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libthrcputime001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libmonitorwaited001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libForceEarlyReturn001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentthr003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentthr002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libagentthr001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcompmethunload001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libretransform002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libretransform004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libretransform003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmdf007 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmdf006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmdf004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetclmdf005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetlocal001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetlocal004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetlocal003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetlocal002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libcompmethload001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsysprops001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetsysprops002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdrrawmon003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdrrawmon004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libdrrawmon001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsinglestep001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsinglestep003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsinglestep002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librelcaps001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_librelcaps002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw004 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw003 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw005 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw006 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libsetfmodw001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libvmdeath001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetphase001 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libgetphase002 += -pthread + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libterminatedThread += -pthread +endif + +# This evaluation is expensive and should only be done if this target was +# explicitly called. +ifneq ($(filter build-test-hotspot-jtreg-native, $(MAKECMDGOALS)), ) + $(eval $(call SetupTestFilesCompilation,BUILD_HOTSPOT_JTREG_LIBRARIES, \ + TYPE := LIBRARY, \ + SOURCE_DIRS := $(BUILD_HOTSPOT_JTREG_NATIVE_SRC)/vmTestbase, \ + OUTPUT_DIR := $(BUILD_HOTSPOT_JTREG_OUTPUT_DIR), \ + EXCLUDE := $(BUILD_HOTSPOT_JTREG_EXCLUDE))) + $(eval $(call SetupTestFilesCompilation,BUILD_HOTSPOT_JTREG_EXECUTABLES, \ + TYPE := PROGRAM, \ + SOURCE_DIRS := $(BUILD_HOTSPOT_JTREG_NATIVE_SRC)/vmTestbase, \ + OUTPUT_DIR := $(BUILD_HOTSPOT_JTREG_OUTPUT_DIR), \ + EXCLUDE := $(BUILD_HOTSPOT_JTREG_EXCLUDE))) +endif +build-test-hotspot-jtreg-native: $(BUILD_HOTSPOT_JTREG_LIBRARIES) $(BUILD_HOTSPOT_JTREG_EXECUTABLES) + @echo "build-test-hotspot" + +################################################################################ +# Targets for building test-image. +################################################################################ + +# Copy to hotspot jtreg test image +$(eval $(call SetupCopyFiles,COPY_HOTSPOT_JTREG_NATIVE, \ + SRC := $(BUILD_HOTSPOT_JTREG_OUTPUT_DIR), \ + DEST := $(IMAGES_OUTPUTDIR)/test/hotspot/jtreg/native, \ + FILES := $(wildcard $(addprefix $(BUILD_HOTSPOT_JTREG_OUTPUT_DIR), /bin/* /lib/*)), \ + FLATTEN := true)) + +test-image-hotspot-jtreg-native: $(COPY_HOTSPOT_JTREG_NATIVE) + @echo "test-image-hotspot" +all: build-test-hotspot-jtreg-native +test-image: test-image-hotspot-jtreg-native + +.PHONY: default all build-test-hotspot-jtreg-native test-image-hotspot-jtreg-native test-image diff -r 5b3afcfc9926 test/TEST.ROOT --- a/test/TEST.ROOT Mon Aug 19 16:33:25 2019 +0300 +++ b/test/TEST.ROOT Fri Sep 06 18:21:51 2019 +0300 @@ -27,7 +27,32 @@ # It also contains test-suite configuration information. # The list of keywords supported in this test suite -keys=cte_test jcmd nmt regression gc stress +keys=cte_test jcmd nmt regression gc stress metaspace headful intermittent groups=TEST.groups [closed/TEST.groups] -requires.properties=sun.arch.data.model + +# Source files for classes that will be used at the beginning of each test suite run, +# to determine additional characteristics of the system for use with the @requires tag. +# Note: compiled bootlibs code will be located in the folder 'bootClasses' +requires.extraPropDefns = jtreg-ext/requires/VMProps.java +requires.extraPropDefns.bootlibs = test/lib/sun test/lib/jdk/test/lib/Platform.java +requires.extraPropDefns.vmOpts = -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:bootClasses + +requires.properties= \ + sun.arch.data.model \ + vm.simpleArch \ + vm.bits \ + vm.flightRecorder \ + vm.jvmci \ + vm.emulatedClient \ + vm.cpu.features \ + vm.debug \ + vm.hasSA \ + vm.hasSAandCanAttach \ + vm.hasCompactString \ + vm.rtm.cpu \ + vm.rtm.compiler \ + vm.compiler1.enabled \ + vm.compiler2.enabled \ + docker.support \ + test.vm.gc.nvdimm diff -r 5b3afcfc9926 test/TestFilesCompilation.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/TestFilesCompilation.gmk Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,107 @@ +# +# Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +ifndef _TEST_FILES_COMPILATION_GMK +_TEST_FILES_COMPILATION_GMK := 1 + +ifeq (,$(_MAKEBASE_GMK)) + $(error You must include MakeBase.gmk prior to including TestFilesCompilation.gmk) +endif + + +include NativeCompilation.gmk + +# Setup make rules for creating a set of native test files (libraries or +# executables). This will locate native files matching a certain pattern, +# and compile these into libraries or executables. +# +# Parameter 1 is the name of the rule. This name is used as variable prefix, +# and the targets generated are listed in a variable by that name. +# +# Remaining parameters are named arguments. These include: +# TYPE Must be either PROGRAM or LIBRARY. +# SOURCE_DIRS A list of source directories to search +# OUTPUT_DIR Where to put the resulting files +# EXCLUDE A list of filenames to exclude from compilation +define SetupTestFilesCompilation + $(foreach i,2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26, $(if $($i),$1_$(strip $($i)))$(NEWLINE)) + $(call LogSetupMacroEntry,SetupTestFilesCompilation($1),$2,$3,$4,$5,$6,$7,$8,$9,$(10),$(11),$(12),$(13),$(14),$(15),$(16),$(17),$(18),$(19),$(20),$(21),$(22),$(23),$(24),$(25),$(26)) + + # Check for duplicate base file names. That would have failed later anyhow, but + # this gives a better error message. + $1_DUPLICATED_NAMES := $$(call dups, $$(notdir $$($1_FILE_LIST))) + ifneq ($$($1_DUPLICATED_NAMES), ) + $$(error There are duplicate test file names for $1: $$($1_DUPLICATED_NAMES)) + endif + + # The list to depend on starts out empty + $1 := + ifeq ($$($1_TYPE), LIBRARY) + $1_PREFIX = lib + $1_OUTPUT_SUBDIR := lib + $1_BASE_CFLAGS := $(CFLAGS_JDKLIB) + $1_LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN) + $1_COMPILATION_TYPE := LIBRARY + else ifeq ($$($1_TYPE), PROGRAM) + $1_PREFIX = exe + $1_OUTPUT_SUBDIR := bin + $1_BASE_CFLAGS := $(CFLAGS_JDKEXE) + $1_LDFLAGS := $(LDFLAGS_JDKEXE) $(LDFLAGS_TESTEXE) + $1_COMPILATION_TYPE := EXECUTABLE + else + $$(error Unknown type: $$($1_TYPE)) + endif + + # Locate all files with the matching prefix + $1_FILE_LIST := \ + $$(call ShellFindFiles, $$($1_SOURCE_DIRS), $$($1_PREFIX)*.c) + + $1_EXCLUDE_PATTERN := $$(addprefix %/, $$($1_EXCLUDE)) + $1_FILTERED_FILE_LIST := $$(filter-out $$($1_EXCLUDE_PATTERN), $$($1_FILE_LIST)) + + # Setup a compilation for each and every one of them + $$(foreach file, $$($1_FILTERED_FILE_LIST), \ + $$(eval name := $$(strip $$(basename $$(notdir $$(file))))) \ + $$(eval unprefixed_name := $$(patsubst $$($1_PREFIX)%, %, $$(name))) \ + $$(eval $$(call SetupNativeCompilation,BUILD_TEST_$$(unprefixed_name), \ + LIBRARY := $$(unprefixed_name), \ + EXTRA_FILES := $$(file), \ + OUTPUT_DIR := $$($1_OUTPUT_DIR)/$$($1_OUTPUT_SUBDIR), \ + OBJECT_DIR := $$($1_OUTPUT_DIR)/support/$$(name), \ + LANG := C, \ + CFLAGS := $$($1_BASE_CFLAGS) $$($1_CFLAGS) $$($1_CFLAGS_$$(name)), \ + LDFLAGS := $$($1_LDFLAGS) $$($1_LDFLAGS_$$(name)) $$($1_LIBS_$$(name)), \ + DISABLED_WARNINGS_gcc := format undef unused-function unused-value, \ + DISABLED_WARNINGS_clang := undef format-nonliteral \ + missing-field-initializers sometimes-uninitialized, \ + OPTIMIZATION := $$(if $$($1_OPTIMIZATION_$$(name)),$$($1_OPTIMIZATION_$$(name)),LOW), \ + COPY_DEBUG_SYMBOLS := false, \ + STRIP_SYMBOLS := false \ + ) ) \ + $$(eval $1 += $$(BUILD_TEST_$$(unprefixed_name)) ) \ + ) +endef + +endif # _TEST_FILES_COMPILATION_GMK diff -r 5b3afcfc9926 test/jtreg-ext/requires/VMProps.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jtreg-ext/requires/VMProps.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package requires; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Platform; +import sun.hotspot.WhiteBox; +import sun.hotspot.code.Compiler; +import sun.hotspot.cpuinfo.CPUInfo; + +/** + * The Class to be invoked by jtreg prior Test Suite execution to + * collect information about VM. + * Do not use any APIs that may not be available in all target VMs. + * Properties set by this Class will be available in the @requires expressions. + */ +public class VMProps implements Callable> { + // value known to jtreg as an indicator of error state + private static final String ERROR_STATE = "__ERROR__"; + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static class SafeMap { + private final Map map = new HashMap<>(); + + public void put(String key, Supplier s) { + String value; + try { + value = s.get(); + } catch (Throwable t) { + System.err.println("failed to get value for " + key); + t.printStackTrace(System.err); + value = ERROR_STATE + t; + } + map.put(key, value); + } + } + + /** + * Collects information about VM properties. + * This method will be invoked by jtreg. + * + * @return Map of property-value pairs. + */ + @Override + public Map call() { + SafeMap map = new SafeMap(); + map.put("vm.flavor", this::vmFlavor); + map.put("vm.compMode", this::vmCompMode); + map.put("vm.bits", this::vmBits); + map.put("vm.flightRecorder", this::vmFlightRecorder); + map.put("vm.simpleArch", this::vmArch); + map.put("vm.emulatedClient", this::vmEmulatedClient); + // vm.hasSA is "true" if the VM contains the serviceability agent + // and jhsdb. + map.put("vm.hasSA", this::vmHasSA); + // vm.hasSAandCanAttach is "true" if the VM contains the serviceability agent + // and jhsdb and it can attach to the VM. + map.put("vm.hasSAandCanAttach", this::vmHasSAandCanAttach); + // vm.hasJFR is "true" if JFR is included in the build of the VM and + // so tests can be executed. + map.put("vm.hasCompactString", this::vmHasCompactString); + map.put("vm.cpu.features", this::cpuFeatures); + map.put("vm.rtm.cpu", this::vmRTMCPU); + map.put("vm.rtm.compiler", this::vmRTMCompiler); + map.put("vm.compiler1.enabled", this::isCompiler1Enabled); + map.put("vm.compiler2.enabled", this::isCompiler2Enabled); + map.put("docker.support", this::dockerSupport); + //map.put("release.implementor", this::implementor); + map.put("test.vm.gc.nvdimm", this::isNvdimmTestEnabled); + vmOptFinalFlags(map); + + dump(map.map); + return map.map; + } + + /** + * Print a stack trace before returning error state; + * Used by the various helper functions which parse information from + * VM properties in the case where they don't find an expected property + * or a property doesn't conform to an expected format. + * + * @return {@link #ERROR_STATE} + */ + private String errorWithMessage(String message) { + new Exception(message).printStackTrace(); + return ERROR_STATE + message; + } + + /** + * @return vm.simpleArch value of "os.simpleArch" property of tested JDK. + */ + protected String vmArch() { + String arch = System.getProperty("os.arch"); + if (arch.equals("x86_64") || arch.equals("amd64")) { + return "x64"; + } else if (arch.contains("86")) { + return "x86"; + } else { + return arch; + } + } + + /** + * @return VM type value extracted from the "java.vm.name" property. + */ + protected String vmFlavor() { + // E.g. "Java HotSpot(TM) 64-Bit Server VM" + String vmName = System.getProperty("java.vm.name"); + if (vmName == null) { + return errorWithMessage("Can't get 'java.vm.name' property"); + } + + Pattern startP = Pattern.compile(".* (\\S+) VM"); + Matcher m = startP.matcher(vmName); + if (m.matches()) { + return m.group(1).toLowerCase(); + } + return errorWithMessage("Can't get VM flavor from 'java.vm.name'"); + } + + /** + * @return VM compilation mode extracted from the "java.vm.info" property. + */ + protected String vmCompMode() { + // E.g. "mixed mode" + String vmInfo = System.getProperty("java.vm.info"); + if (vmInfo == null) { + return errorWithMessage("Can't get 'java.vm.info' property"); + } + vmInfo = vmInfo.toLowerCase(); + if (vmInfo.contains("mixed mode")) { + return "Xmixed"; + } else if (vmInfo.contains("compiled mode")) { + return "Xcomp"; + } else if (vmInfo.contains("interpreted mode")) { + return "Xint"; + } else { + return errorWithMessage("Can't get compilation mode from 'java.vm.info'"); + } + } + + /** + * @return VM bitness, the value of the "sun.arch.data.model" property. + */ + protected String vmBits() { + String dataModel = System.getProperty("sun.arch.data.model"); + if (dataModel != null) { + return dataModel; + } else { + return errorWithMessage("Can't get 'sun.arch.data.model' property"); + } + } + + /** + * @return "true" if Flight Recorder is enabled, "false" if is disabled. + */ + protected String vmFlightRecorder() { + Boolean isFlightRecorder = WB.getBooleanVMFlag("FlightRecorder"); + String startFROptions = WB.getStringVMFlag("StartFlightRecording"); + if (isFlightRecorder != null && isFlightRecorder) { + return "true"; + } + if (startFROptions != null && !startFROptions.isEmpty()) { + return "true"; + } + return "false"; + } + + /** + * @return debug level value extracted from the "jdk.debug" property. + */ + protected String vmDebug() { + String debug = System.getProperty("jdk.debug"); + if (debug != null) { + return "" + debug.contains("debug"); + } else { + return errorWithMessage("Can't get 'jdk.debug' property"); + } + } + + /** + * @return true if VM supports JVMCI and false otherwise + */ + protected String vmJvmci() { + // builds with jvmci have this flag + return "" + (WB.getBooleanVMFlag("EnableJVMCI") != null); + } + + /** + * @return true if VM runs in emulated-client mode and false otherwise. + */ + protected String vmEmulatedClient() { + String vmInfo = System.getProperty("java.vm.info"); + if (vmInfo == null) { + return errorWithMessage("Can't get 'java.vm.info' property"); + } + return "" + vmInfo.contains(" emulated-client"); + } + + /** + * @return supported CPU features + */ + protected String cpuFeatures() { + return CPUInfo.getFeatures().toString(); + } + + /** + * Selected final flag. + * + * @param map - property-value pairs + * @param flagName - flag name + */ + private void vmOptFinalFlag(SafeMap map, String flagName) { + map.put("vm.opt.final." + flagName, + () -> String.valueOf(WB.getBooleanVMFlag(flagName))); + } + + /** + * Selected sets of final flags. + * + * @param map - property-value pairs + */ + protected void vmOptFinalFlags(SafeMap map) { + vmOptFinalFlag(map, "ClassUnloading"); + vmOptFinalFlag(map, "UseCompressedOops"); + vmOptFinalFlag(map, "EliminateAllocations"); + } + + /** + * @return "true" if VM has a serviceability agent. + */ + protected String vmHasSA() { + return "" + Platform.hasSA(); + } + + /** + * @return "true" if VM has a serviceability agent and it can + * attach to the VM. + */ + protected String vmHasSAandCanAttach() { + try { + return "" + Platform.shouldSAAttach(); + } catch (IOException e) { + e.printStackTrace(); + return errorWithMessage("Checking whether SA can attach to the VM failed.:" + e); + } + } + + /** + * @return "true" if the VM implements JEP 254: Compact Strings + * support. + */ + protected String vmHasCompactString() { + return "false"; + } + /** + * @return true if compiler in use supports RTM and false otherwise. + */ + protected String vmRTMCompiler() { + boolean isRTMCompiler = false; + + if (Compiler.isC2Enabled() && + (Platform.isX86() || Platform.isX64() || Platform.isPPC())) { + isRTMCompiler = true; + } + return "" + isRTMCompiler; + } + + /** + * @return true if VM runs RTM supported CPU and false otherwise. + */ + protected String vmRTMCPU() { + return "" + CPUInfo.hasFeature("rtm"); + } + + /** + * Check if Compiler1 is present. + * + * @return true if Compiler1 is used as JIT compiler, either alone or as part of the tiered system. + */ + protected String isCompiler1Enabled() { + return "" + Compiler.isC1Enabled(); + } + + /** + * Check if Compiler2 is present. + * + * @return true if Compiler2 is used as JIT compiler, either alone or as part of the tiered system. + */ + protected String isCompiler2Enabled() { + return "" + Compiler.isC2Enabled(); + } + + /** + * A simple check for docker support + * + * @return true if docker is supported in a given environment + */ + protected String dockerSupport() { + boolean isSupported = false; + if (Platform.isLinux()) { + // currently docker testing is only supported for Linux, + // on certain platforms + + String arch = System.getProperty("os.arch"); + + if (Platform.isX64()) { + isSupported = true; + } else if (Platform.isAArch64()) { + isSupported = true; + } else if (Platform.isS390x()) { + isSupported = true; + } else if (arch.equals("ppc64le")) { + isSupported = true; + } + } + + if (isSupported) { + try { + isSupported = checkDockerSupport(); + } catch (Exception e) { + isSupported = false; + } + } + + return "" + isSupported; + } + + private boolean checkDockerSupport() throws IOException, InterruptedException { + ProcessBuilder pb = new ProcessBuilder("docker", "ps"); + Process p = pb.start(); + p.waitFor(10, TimeUnit.SECONDS); + + return (p.exitValue() == 0); + } + + private String implementor() { + try (InputStream in = new BufferedInputStream(new FileInputStream( + System.getProperty("java.home") + "/release"))) { + Properties properties = new Properties(); + properties.load(in); + String implementorProperty = properties.getProperty("IMPLEMENTOR"); + if (implementorProperty != null) { + return implementorProperty.replace("\"", ""); + } + return errorWithMessage("Can't get 'IMPLEMENTOR' property from 'release' file"); + } catch (IOException e) { + e.printStackTrace(); + return errorWithMessage("Failed to read 'release' file " + e); + } + } + + private String isNvdimmTestEnabled() { + String isEnabled = System.getenv("TEST_VM_GC_NVDIMM"); + return "" + "true".equalsIgnoreCase(isEnabled); + } + + /** + * Dumps the map to the file if the file name is given as the property. + * This functionality could be helpful to know context in the real + * execution. + * + * @param map + */ + protected static void dump(Map map) { + String dumpFileName = System.getProperty("vmprops.dump"); + if (dumpFileName == null) { + return; + } + List lines = new ArrayList<>(); + map.forEach((k, v) -> lines.add(k + ":" + v)); + try { + Files.write(Paths.get(dumpFileName), lines, + StandardOpenOption.APPEND, StandardOpenOption.CREATE); + } catch (IOException e) { + throw new RuntimeException("Failed to dump properties into '" + + dumpFileName + "'", e); + } + } + + /** + * This method is for the testing purpose only. + * + * @param args + */ + public static void main(String args[]) { + Map map = new VMProps().call(); + map.forEach((k, v) -> System.out.println(k + ": '" + v + "'")); + } +} diff -r 5b3afcfc9926 test/test/lib/ClassFileInstaller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/ClassFileInstaller.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.ByteArrayInputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +/** + * Dump a class file for a class on the class path in the current directory, or + * in the specified JAR file. This class is usually used when you build a class + * from a test library, but want to use this class in a sub-process. + * + * For example, to build the following library class: + * test/lib/sun/hotspot/WhiteBox.java + * + * You would use the following tags: + * + * @library /test/lib + * @build sun.hotspot.WhiteBox + * + * JTREG would build the class file under + * ${JTWork}/classes/test/lib/sun/hotspot/WhiteBox.class + * + * With you run your main test class using "@run main MyMainClass", JTREG would setup the + * -classpath to include "${JTWork}/classes/test/lib/", so MyMainClass would be able to + * load the WhiteBox class. + * + * However, if you run a sub process, and do not wish to use the exact same -classpath, + * You can use ClassFileInstaller to ensure that WhiteBox is available in the current + * directory of your test: + * + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * + * Or, you can use the -jar option to store the class in the specified JAR file. If a relative + * path name is given, the JAR file would be relative to the current directory of + * + * @run main ClassFileInstaller -jar myjar.jar sun.hotspot.WhiteBox + */ +public class ClassFileInstaller { + /** + * You can enable debug tracing of ClassFileInstaller by running JTREG with + * jtreg -DClassFileInstaller.debug=true ... + */ + public static boolean DEBUG = Boolean.getBoolean("ClassFileInstaller.debug"); + + /** + * @param args The names of the classes to dump + * @throws Exception + */ + public static void main(String... args) throws Exception { + if (args.length > 1 && args[0].equals("-jar")) { + if (args.length < 2) { + throw new RuntimeException("Usage: ClassFileInstaller \n" + + "where possible options include:\n" + + " -jar Write to the JAR file "); + } + writeJar(args[1], null, args, 2, args.length); + } else { + if (DEBUG) { + System.out.println("ClassFileInstaller: Writing to " + System.getProperty("user.dir")); + } + for (String arg : args) { + writeClassToDisk(arg); + } + } + } + + public static class Manifest { + private InputStream in; + + private Manifest(InputStream in) { + this.in = in; + } + + static Manifest fromSourceFile(String fileName) throws Exception { + String pathName = System.getProperty("test.src") + File.separator + fileName; + return new Manifest(new FileInputStream(pathName)); + } + + // Example: + // String manifest = "Premain-Class: RedefineClassHelper\n" + + // "Can-Redefine-Classes: true\n"; + // ClassFileInstaller.writeJar("redefineagent.jar", + // ClassFileInstaller.Manifest.fromString(manifest), + // "RedefineClassHelper"); + static Manifest fromString(String manifest) throws Exception { + return new Manifest(new ByteArrayInputStream(manifest.getBytes())); + } + + public InputStream getInputStream() { + return in; + } + } + + private static void writeJar(String jarFile, Manifest manifest, String classes[], int from, int to) throws Exception { + if (DEBUG) { + System.out.println("ClassFileInstaller: Writing to " + getJarPath(jarFile)); + } + + (new File(jarFile)).delete(); + FileOutputStream fos = new FileOutputStream(jarFile); + ZipOutputStream zos = new ZipOutputStream(fos); + + // The manifest must be the first or second entry. See comments in JarInputStream + // constructor and JDK-5046178. + if (manifest != null) { + writeToDisk(zos, "META-INF/MANIFEST.MF", manifest.getInputStream()); + } + + for (int i=from; i 0) { + pathName = prependPath + "/" + pathName; + } + writeToDisk(zos, pathName, is); + } + + public static void writeClassToDisk(String className, byte[] bytecode) throws Exception { + writeClassToDisk(null, className, bytecode); + } + private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode) throws Exception { + writeClassToDisk(zos, className, bytecode, ""); + } + + public static void writeClassToDisk(String className, byte[] bytecode, String prependPath) throws Exception { + writeClassToDisk(null, className, bytecode, prependPath); + } + private static void writeClassToDisk(ZipOutputStream zos, String className, byte[] bytecode, String prependPath) throws Exception { + // Convert dotted class name to a path to a class file + String pathName = className.replace('.', '/').concat(".class"); + if (prependPath.length() > 0) { + pathName = prependPath + "/" + pathName; + } + writeToDisk(zos, pathName, new ByteArrayInputStream(bytecode)); + } + + private static void writeToDisk(ZipOutputStream zos, String pathName, InputStream is) throws Exception { + if (DEBUG) { + System.out.println("ClassFileInstaller: Writing " + pathName); + } + if (zos != null) { + ZipEntry ze = new ZipEntry(pathName); + zos.putNextEntry(ze); + byte[] buf = new byte[1024]; + int len; + while ((len = is.read(buf))>0){ + zos.write(buf, 0, len); + } + } else { + // Create the class file's package directory + Path p = Paths.get(pathName); + if (pathName.contains("/")) { + Files.createDirectories(p.getParent()); + } + // Create the class file + Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); + } + is.close(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/Asserts.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/Asserts.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,620 @@ +/* + * 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 jdk.test.lib; + +import java.util.Objects; + +/** + * Asserts that can be used for verifying assumptions in tests. + * + * An assertion will throw a {@link RuntimeException} if the assertion isn't true. + * All the asserts can be imported into a test by using a static import: + * + *
+ * {@code
+ * import static jdk.test.lib.Asserts.*;
+ * }
+ *
+ * Always provide a message describing the assumption if the line number of the
+ * failing assertion isn't enough to understand why the assumption failed. For
+ * example, if the assertion is in a loop or in a method that is called
+ * multiple times, then the line number won't provide enough context to
+ * understand the failure.
+ * 
+ */ +public class Asserts { + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable) + */ + public static > void assertLT(T lhs, T rhs) { + assertLessThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLT(T lhs, T rhs, String msg) { + assertLessThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThan(Comparable, Comparable, String) + */ + public static > void assertLessThan(T lhs, T rhs) { + assertLessThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static >void assertLessThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) < 0)) { + msg = Objects.toString(msg, "assertLessThan") + + ": expected that " + Objects.toString(lhs) + + " < " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable) + */ + public static > void assertLTE(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLTE(T lhs, T rhs, String msg) { + assertLessThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertLessThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertLessThanOrEqual(T lhs, T rhs) { + assertLessThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is less than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertLessThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) <= 0)) { + msg = Objects.toString(msg, "assertLessThanOrEqual") + + ": expected that " + Objects.toString(lhs) + + " <= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object) + */ + public static void assertEQ(Object lhs, Object rhs) { + assertEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEQ(Object lhs, Object rhs, String msg) { + assertEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertEquals(Object, Object, String) + */ + public static void assertEquals(Object lhs, Object rhs) { + assertEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertEquals(Object lhs, Object rhs, String msg) { + if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) { + msg = Objects.toString(msg, "assertEquals") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertSame(Object, Object, String) + */ + public static void assertSame(Object lhs, Object rhs) { + assertSame(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is the same as {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertSame(Object lhs, Object rhs, String msg) { + if (lhs != rhs) { + msg = Objects.toString(msg, "assertSame") + + ": expected " + Objects.toString(lhs) + + " to equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable) + */ + public static > void assertGTE(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGTE(T lhs, T rhs, String msg) { + assertGreaterThanOrEqual(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThanOrEqual(Comparable, Comparable, String) + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs) { + assertGreaterThanOrEqual(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than or equal to {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThanOrEqual(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) >= 0)) { + msg = Objects.toString(msg, "assertGreaterThanOrEqual") + + ": expected " + Objects.toString(lhs) + + " >= " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertGreaterThan(Comparable, Comparable) + */ + public static > void assertGT(T lhs, T rhs) { + assertGreaterThan(lhs, rhs); + } + + /** + * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGT(T lhs, T rhs, String msg) { + assertGreaterThan(lhs, rhs, msg); + } + + /** + * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message. + * + * @param a type + * @param lhs the left hand value + * @param rhs the right hand value + * @see #assertGreaterThan(Comparable, Comparable, String) + */ + public static > void assertGreaterThan(T lhs, T rhs) { + assertGreaterThan(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is greater than {@code rhs}. + * + * @param a type + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static > void assertGreaterThan(T lhs, T rhs, String msg) { + if (!(compare(lhs, rhs, msg) > 0)) { + msg = Objects.toString(msg, "assertGreaterThan") + + ": expected " + Objects.toString(lhs) + + " > " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object) + */ + public static void assertNE(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs); + } + + /** + * Shorthand for {@link #assertNotEquals(Object, Object, String)}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNE(Object lhs, Object rhs, String msg) { + assertNotEquals(lhs, rhs, msg); + } + + /** + * Calls {@link #assertNotEquals(Object, Object, String)} with a default message. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @see #assertNotEquals(Object, Object, String) + */ + public static void assertNotEquals(Object lhs, Object rhs) { + assertNotEquals(lhs, rhs, null); + } + + /** + * Asserts that {@code lhs} is not equal to {@code rhs}. + * + * @param lhs The left hand side of the comparison. + * @param rhs The right hand side of the comparison. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotEquals(Object lhs, Object rhs, String msg) { + if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) { + msg = Objects.toString(msg, "assertNotEquals") + + ": expected " + Objects.toString(lhs) + + " to not equal " + Objects.toString(rhs); + fail(msg); + } + } + + /** + * Calls {@link #assertNull(Object, String)} with a default message. + * + * @param o The reference assumed to be null. + * @see #assertNull(Object, String) + */ + public static void assertNull(Object o) { + assertNull(o, null); + } + + /** + * Asserts that {@code o} is null. + * + * @param o The reference assumed to be null. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNull(Object o, String msg) { + assertEquals(o, null, msg); + } + + /** + * Calls {@link #assertNotNull(Object, String)} with a default message. + * + * @param o The reference assumed not to be null, + * @see #assertNotNull(Object, String) + */ + public static void assertNotNull(Object o) { + assertNotNull(o, null); + } + + /** + * Asserts that {@code o} is not null. + * + * @param o The reference assumed not to be null, + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertNotNull(Object o, String msg) { + assertNotEquals(o, null, msg); + } + + /** + * Calls {@link #assertFalse(boolean, String)} with a default message. + * + * @param value The value assumed to be false. + * @see #assertFalse(boolean, String) + */ + public static void assertFalse(boolean value) { + assertFalse(value, null); + } + + /** + * Asserts that {@code value} is {@code false}. + * + * @param value The value assumed to be false. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertFalse(boolean value, String msg) { + if (value) { + msg = Objects.toString(msg, "assertFalse") + + ": expected false, was true"; + fail(msg); + } + } + + /** + * Calls {@link #assertTrue(boolean, String)} with a default message. + * + * @param value The value assumed to be true. + * @see #assertTrue(boolean, String) + */ + public static void assertTrue(boolean value) { + assertTrue(value, null); + } + + /** + * Asserts that {@code value} is {@code true}. + * + * @param value The value assumed to be true. + * @param msg A description of the assumption; {@code null} for a default message. + * @throws RuntimeException if the assertion is not true. + */ + public static void assertTrue(boolean value, String msg) { + if (!value) { + msg = Objects.toString(msg, "assertTrue") + + ": expected true, was false"; + fail(msg); + } + } + + private static > int compare(T lhs, T rhs, String msg) { + if (lhs == null || rhs == null) { + fail(lhs, rhs, msg + ": values must be non-null:", ","); + } + return lhs.compareTo(rhs); + } + +/** + * Asserts that two strings are equal. + * + * If strings are not equals, then exception message + * will contain {@code msg} followed by list of mismatched lines. + * + * @param str1 First string to compare. + * @param str2 Second string to compare. + * @param msg A description of the assumption. + * @throws RuntimeException if strings are not equal. + */ + public static void assertStringsEqual(String str1, String str2, + String msg) { + String lineSeparator = System.getProperty("line.separator"); + String str1Lines[] = str1.split(lineSeparator); + String str2Lines[] = str2.split(lineSeparator); + + int minLength = Math.min(str1Lines.length, str2Lines.length); + String longestStringLines[] = ((str1Lines.length == minLength) ? + str2Lines : str1Lines); + + boolean stringsAreDifferent = false; + + StringBuilder messageBuilder = new StringBuilder(msg); + + messageBuilder.append("\n"); + + for (int line = 0; line < minLength; line++) { + if (!str1Lines[line].equals(str2Lines[line])) { + messageBuilder.append(String. + format("[line %d] '%s' differs " + + "from '%s'\n", + line, + str1Lines[line], + str2Lines[line])); + stringsAreDifferent = true; + } + } + + if (minLength < longestStringLines.length) { + String stringName = ((longestStringLines == str1Lines) ? + "first" : "second"); + messageBuilder.append(String.format("Only %s string contains " + + "following lines:\n", + stringName)); + stringsAreDifferent = true; + for(int line = minLength; line < longestStringLines.length; line++) { + messageBuilder.append(String. + format("[line %d] '%s'", line, + longestStringLines[line])); + } + } + + if (stringsAreDifferent) { + fail(messageBuilder.toString()); + } + } + + /** + * Returns a string formatted with a message and expected and actual values. + * @param lhs the actual value + * @param rhs the expected value + * @param message the actual value + * @param relation the asserted relationship between lhs and rhs + * @return a formatted string + */ + public static String format(Object lhs, Object rhs, String message, String relation) { + StringBuilder sb = new StringBuilder(80); + if (message != null) { + sb.append(message); + sb.append(' '); + } + sb.append("<"); + sb.append(Objects.toString(lhs)); + sb.append("> "); + sb.append(Objects.toString(relation, ",")); + sb.append(" <"); + sb.append(Objects.toString(rhs)); + sb.append(">"); + return sb.toString(); + } + + /** + * Fail reports a failure with message fail. + * + * @throws RuntimeException always + */ + public static void fail() { + fail("fail"); + } + + /** + * Fail reports a failure with a message. + * @param message for the failure + * @throws RuntimeException always + */ + public static void fail(String message) { + throw new RuntimeException(message); + } + + /** + * Fail reports a failure with a formatted message. + * + * @param lhs the actual value + * @param rhs the expected value + * @param message to be format before the expected and actual values + * @param relation the asserted relationship between lhs and rhs + * @throws RuntimeException always + */ + public static void fail(Object lhs, Object rhs, String message, String relation) { + throw new RuntimeException(format(lhs, rhs, message, relation)); + } + + /** + * Fail reports a failure with a message and a cause. + * @param message to be format before the expected and actual values + * @param cause the exception that caused this failure + * @throws RuntimeException always + */ + public static void fail(String message, Throwable cause) { + throw new RuntimeException(message, cause); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/BuildHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/BuildHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.File; +import java.io.FileReader; +import java.util.Properties; + +public class BuildHelper { + + /** + * Commercial builds should have the BUILD_TYPE set to commercial + * within the release file, found at the root of the JDK. + */ + public static boolean isCommercialBuild() throws Exception { + String buildType = getReleaseProperty("BUILD_TYPE","notFound"); + return buildType.equals("commercial"); + } + + + /** + * Return the value for property key, or defaultValue if no property not found. + * If present, double quotes are trimmed. + */ + public static String getReleaseProperty(String key, String defaultValue) throws Exception { + Properties properties = getReleaseProperties(); + String value = properties.getProperty(key, defaultValue); + return trimDoubleQuotes(value); + } + + /** + * Return the value for property key, or null if no property not found. + * If present, double quotes are trimmed. + */ + public static String getReleaseProperty(String key) throws Exception { + return getReleaseProperty(key, null); + } + + /** + * Get properties from the release file + */ + public static Properties getReleaseProperties() throws Exception { + Properties properties = new Properties(); + properties.load(new FileReader(getReleaseFile())); + return properties; + } + + /** + * Every JDK has a release file in its root. + * @return A handler to the release file. + */ + public static File getReleaseFile() throws Exception { + String jdkPath = getJDKRoot(); + File releaseFile = new File(jdkPath,"release"); + if ( ! releaseFile.canRead() ) { + throw new Exception("Release file is not readable, or it is absent: " + + releaseFile.getCanonicalPath()); + } + return releaseFile; + } + + /** + * Returns path to the JDK under test. + * This path is obtained through the test.jdk property, usually set by JTREG. + */ + public static String getJDKRoot() { + String jdkPath = System.getProperty("test.jdk"); + if (jdkPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + return jdkPath; + } + + /** + * Trim double quotes from the beginning and the end of the given string. + * @param original string to trim. + * @return a new trimmed string. + */ + public static String trimDoubleQuotes(String original) { + if (original == null) { return null; } + String trimmed = original.replaceAll("^\"+|\"+$", ""); + return trimmed; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/ByteCodeLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/ByteCodeLoader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.security.SecureClassLoader; + +/** + * {@code ByteCodeLoader} can be used for easy loading of byte code already + * present in memory. + * + * {@code InMemoryCompiler} can be used for compiling source code in a string + * into byte code, which then can be loaded with {@code ByteCodeLoader}. + * + * @see InMemoryCompiler + */ +public class ByteCodeLoader extends SecureClassLoader { + private final String className; + private final byte[] byteCode; + private volatile Class holder; + + /** + * Creates a new {@code ByteCodeLoader} ready to load a class with the + * given name and the given byte code. + * + * @param className The name of the class + * @param byteCode The byte code of the class + */ + public ByteCodeLoader(String className, byte[] byteCode) { + this.className = className; + this.byteCode = byteCode; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (!name.equals(className)) { + return super.loadClass(name); + } + if (holder == null) { + synchronized(this) { + if (holder == null) { + holder = findClass(name); + } + } + } + return holder; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (!name.equals(className)) { + throw new ClassNotFoundException(name); + } + + return defineClass(name, byteCode, 0, byteCode.length); + } + + /** + * Utility method for creating a new {@code ByteCodeLoader} and then + * directly load the given byte code. + * + * @param className The name of the class + * @param byteCode The byte code for the class + * @throws ClassNotFoundException if the class can't be loaded + * @return A {@see Class} object representing the class + */ + public static Class load(String className, byte[] byteCode) throws ClassNotFoundException { + return new ByteCodeLoader(className, byteCode).loadClass(className); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/Convert.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/Convert.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,85 @@ +/* + * 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 jdk.test.lib; + +import java.math.BigInteger; + +/** + * Utility class containing conversions between strings, arrays, and numeric + * values. + */ + +public class Convert { + + // Convert from a byte array to a hexadecimal representation as a string. + public static String byteArrayToHexString(byte[] arr) { + StringBuilder result = new StringBuilder(); + for (int i = 0; i < arr.length; ++i) { + byte curVal = arr[i]; + result.append(Character.forDigit(curVal >> 4 & 0xF, 16)); + result.append(Character.forDigit(curVal & 0xF, 16)); + } + return result.toString(); + } + + // Expand a single byte to a byte array + public static byte[] byteToByteArray(byte v, int length) { + byte[] result = new byte[length]; + result[0] = v; + return result; + } + + // Convert a hexadecimal string to a byte array + public static byte[] hexStringToByteArray(String str) { + byte[] result = new byte[str.length() / 2]; + for (int i = 0; i < result.length; i++) { + result[i] = (byte) Character.digit(str.charAt(2 * i), 16); + result[i] <<= 4; + result[i] += Character.digit(str.charAt(2 * i + 1), 16); + } + return result; + } + + /* + * Convert a hexadecimal string to the corresponding little-ending number + * as a BigInteger. The clearHighBit argument determines whether the most + * significant bit of the highest byte should be set to 0 in the result. + */ + public static + BigInteger hexStringToBigInteger(boolean clearHighBit, String str) { + BigInteger result = BigInteger.ZERO; + for (int i = 0; i < str.length() / 2; i++) { + int curVal = Character.digit(str.charAt(2 * i), 16); + curVal <<= 4; + curVal += Character.digit(str.charAt(2 * i + 1), 16); + if (clearHighBit && i == str.length() / 2 - 1) { + curVal &= 0x7F; + } + result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i)); + } + return result; + } +} + + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/FileInstaller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/FileInstaller.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; + +// !!! +// NOTE: this class is widely used. DO NOT depend on any other classes in any test library, or else +// you may see intermittent ClassNotFoundException as in JDK-8188828 +// !!! + +/** + * Copy a resource: file or directory recursively, using relative path(src and dst) + * which are applied to test source directory(src) and current directory(dst) + */ +public class FileInstaller { + public static final String TEST_SRC = System.getProperty("test.src", "").trim(); + + /** + * @param args source and destination + * @throws IOException if an I/O error occurs + */ + public static void main(String[] args) throws IOException { + if (args.length != 2) { + throw new IllegalArgumentException("Unexpected number of arguments for file copy"); + } + Path src = Paths.get(TEST_SRC, args[0]).toAbsolutePath().normalize(); + Path dst = Paths.get(args[1]).toAbsolutePath().normalize(); + if (src.toFile().exists()) { + System.out.printf("copying %s to %s%n", src, dst); + if (src.toFile().isDirectory()) { + // can't use Files::copy for dirs, as 'dst' might exist already + Files.walkFileTree(src, new CopyFileVisitor(src, dst)); + } else { + Path dstDir = dst.getParent(); + if (!dstDir.toFile().exists()) { + Files.createDirectories(dstDir); + } + Files.copy(src, dst, StandardCopyOption.REPLACE_EXISTING); + } + } else { + throw new IOException("Can't find source " + src); + } + } + + private static class CopyFileVisitor extends SimpleFileVisitor { + private final Path copyFrom; + private final Path copyTo; + + public CopyFileVisitor(Path copyFrom, Path copyTo) { + this.copyFrom = copyFrom; + this.copyTo = copyTo; + } + + @Override + public FileVisitResult preVisitDirectory(Path file, + BasicFileAttributes attrs) throws IOException { + Path relativePath = copyFrom.relativize(file); + Path destination = copyTo.resolve(relativePath); + if (!destination.toFile().exists()) { + Files.createDirectories(destination); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attrs) throws IOException { + if (!file.toFile().isFile()) { + return FileVisitResult.CONTINUE; + } + Path relativePath = copyFrom.relativize(file); + Path destination = copyTo.resolve(relativePath); + Files.copy(file, destination, StandardCopyOption.COPY_ATTRIBUTES); + return FileVisitResult.CONTINUE; + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/InfiniteLoop.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/InfiniteLoop.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.Objects; + +/** + * Class which runs another Runnable in infinite loop with certain pauses + * between cycles. + */ +public class InfiniteLoop implements Runnable { + private final Runnable target; + private final long mills; + + + /** + * @param target a target to run in a loop + * @param mills the length of pause time in milliseconds + * @throws NullPointerException if target is null + * @throws IllegalArgumentException if the value of millis is negative + */ + public InfiniteLoop(Runnable target, long mills) { + Objects.requireNonNull(target); + if (mills < 0) { + throw new IllegalArgumentException("mills < 0"); + } + this.target = target; + this.mills = mills; + } + + @Override + public void run() { + try { + while (true) { + target.run(); + if (mills > 0) { + Thread.sleep(mills); + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/JDKToolFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/JDKToolFinder.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/JDKToolLauncher.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/JDKToolLauncher.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.ArrayList; +import java.util.List; + +/** + * A utility for constructing command lines for starting JDK tool processes. + * + * The JDKToolLauncher can in particular be combined with a + * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following + * code run {@code jmap -heap} against a process with GC logging turned on for + * the {@code jmap} process: + * + *
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ *                                       .addVMArg("-XX:+PrintGC");
+ *                                       .addVMArg("-XX:+PrintGCDetails")
+ *                                       .addToolArg("-heap")
+ *                                       .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * 
+ */ +public class JDKToolLauncher { + private final String executable; + private final List vmArgs = new ArrayList(); + private final List toolArgs = new ArrayList(); + + private JDKToolLauncher(String tool, boolean useCompilerJDK) { + if (useCompilerJDK) { + executable = JDKToolFinder.getJDKTool(tool); + } else { + executable = JDKToolFinder.getTestJDKTool(tool); + } + } + + /** + * Creates a new JDKToolLauncher for the specified tool. Using tools path + * from the compiler JDK. + * + * @param tool + * The name of the tool + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher create(String tool) { + return new JDKToolLauncher(tool, true); + } + + /** + * Creates a new JDKToolLauncher for the specified tool in the Tested JDK. + * + * @param tool + * The name of the tool + * + * @return A new JDKToolLauncher + */ + public static JDKToolLauncher createUsingTestJDK(String tool) { + return new JDKToolLauncher(tool, false); + } + + /** + * Adds an argument to the JVM running the tool. + * + * The JVM arguments are passed to the underlying JVM running the tool. + * Arguments will automatically be prepended with "-J". + * + * Any platform specific arguments required for running the tool are + * automatically added. + * + * + * @param arg + * The argument to VM running the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addVMArg(String arg) { + vmArgs.add(arg); + return this; + } + + /** + * Adds an argument to the tool. + * + * @param arg + * The argument to the tool + * @return The JDKToolLauncher instance + */ + public JDKToolLauncher addToolArg(String arg) { + toolArgs.add(arg); + return this; + } + + /** + * Returns the command that can be used for running the tool. + * + * @return An array whose elements are the arguments of the command. + */ + public String[] getCommand() { + List command = new ArrayList(); + command.add(executable); + // Add -J in front of all vmArgs + for (String arg : vmArgs) { + command.add("-J" + arg); + } + command.addAll(toolArgs); + return command.toArray(new String[command.size()]); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/LockFreeLogger.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/LockFreeLogger.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; + +/** + * A logger designed specifically to allow collecting ordered log messages + * in a multi-threaded environment without involving any kind of locking. + *

+ * It is particularly useful in situations when one needs to assert various + * details about the tested thread state or the locks it hold while also wanting + * to produce diagnostic log messages. + *

+ * The logger does not provide any guarantees about the completness of the + * logs written from different threads - it is up to the caller to make sure + * {@code toString()} method is called only when all the activity has ceased + * and the per-thread logs contain all the necessary data. + * + * @author Jaroslav Bachorik + **/ +public class LockFreeLogger { + private final AtomicInteger logCntr = new AtomicInteger(0); + private final Collection> allRecords = new ConcurrentLinkedQueue<>(); + private final ThreadLocal> records = ThreadLocal.withInitial(ConcurrentHashMap::new); + + public LockFreeLogger() { + allRecords.add(records.get()); + } + + /** + * Log a message + * @param format Message format + * @param params Message parameters + */ + public void log(String format, Object ... params) { + int id = logCntr.getAndIncrement(); + records.get().put(id, String.format(format, params)); + } + + /** + * Will generate an aggregated log of chronologically ordered messages. + *

+ * Make sure that you call this method only when all the related threads + * have finished; otherwise you might get incomplete data. + * + * @return An aggregated log of chronologically ordered messages + */ + @Override + public String toString() { + return allRecords.stream() + .flatMap(m -> m.entrySet().stream()) + .sorted(Comparator.comparing(Map.Entry::getKey)) + .map(Map.Entry::getValue) + .collect(Collectors.joining()); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/NetworkConfiguration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/NetworkConfiguration.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.net.NetworkInterface.getNetworkInterfaces; +import static java.util.Collections.list; + +/** + * Helper class for retrieving network interfaces and local addresses + * suitable for testing. + */ +public class NetworkConfiguration { + + private Map> ip4Interfaces; + private Map> ip6Interfaces; + private final boolean isIPv6Available; + private boolean has_testableipv6address = false; + private boolean has_sitelocaladdress = false; + private boolean has_linklocaladdress = false; + private boolean has_globaladdress = false; + + private NetworkConfiguration( + Map> ip4Interfaces, + Map> ip6Interfaces) { + this.ip4Interfaces = ip4Interfaces; + this.ip6Interfaces = ip6Interfaces; + + // initialize properties that can be queried + isIPv6Available = !ip6Interfaces().collect(Collectors.toList()).isEmpty(); + ip6Interfaces().forEach(nif -> { + ip6Addresses(nif) + // On Solaris or AIX, a configuration with only local or loopback + // addresses does not fully enable IPv6 operations. + // E.g. IPv6 multicasting does not work. + // So, don't set has_testableipv6address if we only find these. + .filter(addr -> Platform.isSolaris() || Platform.isAix() ? + !(addr.isAnyLocalAddress() || addr.isLoopbackAddress()) : true) + .forEach(ia -> { + has_testableipv6address = true; + if (ia.isLinkLocalAddress()) has_linklocaladdress = true; + if (ia.isSiteLocalAddress()) has_sitelocaladdress = true; + + if (!ia.isLinkLocalAddress() && + !ia.isSiteLocalAddress() && + !ia.isLoopbackAddress()) { + has_globaladdress = true; + } + }); + }); + } + + private static boolean isNotExcludedInterface(NetworkInterface nif) { + if (Platform.isOSX() && nif.getName().contains("awdl")) { + return false; + } + if (Platform.isWindows()) { + String dName = nif.getDisplayName(); + if (dName != null && dName.contains("Teredo")) { + return false; + } + } + return true; + } + + private static boolean isNotLoopback(NetworkInterface nif) { + try { + return !nif.isLoopback(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private boolean hasIp4Addresses(NetworkInterface nif) { + return ip4Interfaces.get(nif).stream().anyMatch(a -> !a.isAnyLocalAddress()); + } + + private boolean hasIp6Addresses(NetworkInterface nif) { + return ip6Interfaces.get(nif).stream().anyMatch(a -> !a.isAnyLocalAddress()); + } + + private boolean supportsIp4Multicast(NetworkInterface nif) { + try { + if (!nif.supportsMulticast()) { + return false; + } + + // On AIX there is a bug: + // When IPv6 is enabled on the system, the JDK opens sockets as AF_INET6. + // If there's an interface configured with IPv4 addresses only, it should + // be able to become the network interface for a multicast socket (that + // could be in both, IPv4 or IPv6 space). But both possible setsockopt + // calls for either IPV6_MULTICAST_IF or IP_MULTICAST_IF return + // EADDRNOTAVAIL. So we must skip such interfaces here. + if (Platform.isAix() && isIPv6Available() && !hasIp6Addresses(nif)) { + return false; + } + + return hasIp4Addresses(nif); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private boolean supportsIp6Multicast(NetworkInterface nif) { + try { + if (!nif.supportsMulticast()) { + return false; + } + + return hasIp6Addresses(nif); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Returns whether IPv6 is available at all. + * This should resemble the result of native ipv6_available() in net_util.c + */ + public boolean isIPv6Available() { + return isIPv6Available; + } + + /** + * Does any (usable) IPv6 address exist in the network configuration? + */ + public boolean hasTestableIPv6Address() { + return has_testableipv6address; + } + + /** + * Does any site local address exist? + */ + public boolean hasSiteLocalAddress() { + return has_sitelocaladdress; + } + + /** + * Does any link local address exist? + */ + public boolean hasLinkLocalAddress() { + return has_linklocaladdress; + } + + /** + * Does any global IPv6 address exist? + */ + public boolean has_globaladdress() { + return has_globaladdress; + } + + /** + * Returns a stream of interfaces suitable for functional tests. + */ + public Stream interfaces() { + return Stream.concat(ip4Interfaces(), ip6Interfaces()) + .distinct(); + } + + /** + * Returns a stream of interfaces suitable for IPv4 functional tests. + */ + public Stream ip4Interfaces() { + return ip4Interfaces.keySet() + .stream() + .filter(NetworkConfiguration::isNotExcludedInterface) + .filter(this::hasIp4Addresses); + } + + /** + * Returns a stream of interfaces suitable for IPv6 functional tests. + */ + public Stream ip6Interfaces() { + return ip6Interfaces.keySet() + .stream() + .filter(NetworkConfiguration::isNotExcludedInterface) + .filter(this::hasIp6Addresses); + } + + /** + * Returns a stream of interfaces suitable for functional tests. + */ + public Stream multicastInterfaces(boolean includeLoopback) { + return Stream + .concat(ip4MulticastInterfaces(includeLoopback), + ip6MulticastInterfaces(includeLoopback)) + .distinct(); + } + + /** + * Returns a stream of interfaces suitable for IPv4 multicast tests. + * + * The loopback interface will not be included. + */ + public Stream ip4MulticastInterfaces() { + return ip4MulticastInterfaces(false); + } + + /** + * Returns a stream of interfaces suitable for IPv4 multicast tests. + */ + public Stream ip4MulticastInterfaces(boolean includeLoopback) { + return (includeLoopback) ? + ip4Interfaces().filter(this::supportsIp4Multicast) : + ip4Interfaces().filter(this::supportsIp4Multicast) + .filter(NetworkConfiguration::isNotLoopback); + } + + /** + * Returns a stream of interfaces suitable for IPv6 multicast tests. + * + * The loopback interface will not be included. + */ + public Stream ip6MulticastInterfaces() { + return ip6MulticastInterfaces(false); + } + + /** + * Returns a stream of interfaces suitable for IPv6 multicast tests. + */ + public Stream ip6MulticastInterfaces(boolean includeLoopback) { + return (includeLoopback) ? + ip6Interfaces().filter(this::supportsIp6Multicast) : + ip6Interfaces().filter(this::supportsIp6Multicast) + .filter(NetworkConfiguration::isNotLoopback); + } + + /** + * Returns all addresses on all "functional" interfaces. + */ + public Stream addresses(NetworkInterface nif) { + return Stream.concat(ip4Interfaces.get(nif).stream(), + ip6Interfaces.get(nif).stream()); + } + + /** + * Returns all IPv4 addresses on all "functional" interfaces. + */ + public Stream ip4Addresses() { + return ip4Interfaces().flatMap(this::ip4Addresses); + } + + /** + * Returns all IPv6 addresses on all "functional" interfaces. + */ + public Stream ip6Addresses() { + return ip6Interfaces().flatMap(this::ip6Addresses); + } + + /** + * Returns all IPv4 addresses the given interface. + */ + public Stream ip4Addresses(NetworkInterface nif) { + return ip4Interfaces.get(nif).stream(); + } + + /** + * Returns all IPv6 addresses for the given interface. + */ + public Stream ip6Addresses(NetworkInterface nif) { + return ip6Interfaces.get(nif).stream(); + } + + @Override + public String toString() { + return interfaces().map(NetworkConfiguration::interfaceInformation) + .collect(Collectors.joining()); + } + + /** + * Return a NetworkConfiguration instance. + */ + public static NetworkConfiguration probe() throws IOException { + Map> ip4Interfaces = new HashMap<>(); + Map> ip6Interfaces = new HashMap<>(); + + List nifs = list(getNetworkInterfaces()); + for (NetworkInterface nif : nifs) { + // ignore interfaces that are down + if (!nif.isUp() || nif.isPointToPoint()) { + continue; + } + + List ip4Addresses = new LinkedList<>(); + List ip6Addresses = new LinkedList<>(); + ip4Interfaces.put(nif, ip4Addresses); + ip6Interfaces.put(nif, ip6Addresses); + for (InetAddress addr : list(nif.getInetAddresses())) { + if (addr instanceof Inet4Address) { + ip4Addresses.add((Inet4Address) addr); + } else if (addr instanceof Inet6Address) { + ip6Addresses.add((Inet6Address) addr); + } + } + } + return new NetworkConfiguration(ip4Interfaces, ip6Interfaces); + } + + /** Returns detailed information for the given interface. */ + public static String interfaceInformation(NetworkInterface nif) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("Display name: ") + .append(nif.getDisplayName()) + .append("\n"); + sb.append("Name: ") + .append(nif.getName()) + .append("\n"); + for (InetAddress inetAddress : list(nif.getInetAddresses())) { + sb.append("InetAddress: ") + .append(inetAddress) + .append("\n"); + } + sb.append("Up? ") + .append(nif.isUp()) + .append("\n"); + sb.append("Loopback? ") + .append(nif.isLoopback()) + .append("\n"); + sb.append("PointToPoint? ") + .append(nif.isPointToPoint()) + .append("\n"); + sb.append("Supports multicast? ") + .append(nif.supportsMulticast()) + .append("\n"); + sb.append("Virtual? ") + .append(nif.isVirtual()) + .append("\n"); + sb.append("Hardware address: ") + .append(Arrays.toString(nif.getHardwareAddress())) + .append("\n"); + sb.append("MTU: ") + .append(nif.getMTU()) + .append("\n"); + sb.append("Index: ") + .append(nif.getIndex()) + .append("\n"); + sb.append("\n"); + return sb.toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** Prints all the system interface information to the give stream. */ + public static void printSystemConfiguration(PrintStream out) { + try { + out.println("*** all system network interface configuration ***"); + for (NetworkInterface nif : list(getNetworkInterfaces())) { + out.print(interfaceInformation(nif)); + } + out.println("*** end ***"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/OSVersion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/OSVersion.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.Arrays; +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +public final class OSVersion implements Comparable { + public static final OSVersion WINDOWS_95 = new OSVersion(4, 0); + public static final OSVersion WINDOWS_98 = new OSVersion(4, 10); + public static final OSVersion WINDOWS_ME = new OSVersion(4, 90); + public static final OSVersion WINDOWS_2000 = new OSVersion(5, 0); + public static final OSVersion WINDOWS_XP = new OSVersion(5, 1); + public static final OSVersion WINDOWS_2003 = new OSVersion(5, 2); + public static final OSVersion WINDOWS_VISTA = new OSVersion(6, 0); + + private final int[] versionTokens; + + public static OSVersion current() { + if (Platform.isSolaris()) { + return new OSVersion(getSolarisVersion()); + } + return new OSVersion(Platform.getOsVersion()); + } + + public OSVersion(int major, int minor) { + versionTokens = new int[] {major, minor}; + } + + public OSVersion(String version) { + Pattern onlyDigits = Pattern.compile("^\\d+$"); + this.versionTokens = Arrays.stream(version.split("-")[0].split("\\.")) + .filter(onlyDigits.asPredicate()) + .mapToInt(Integer::parseInt) + .toArray(); + } + + private static String getSolarisVersion() { + try { + return Utils.distro(); + } catch (Throwable e) { + System.out.println("First attempt failed with: " + e.getMessage()); + } + + // Try to get Solaris version from /etc/release + try (BufferedReader in = new BufferedReader(AccessController.doPrivileged( + (PrivilegedExceptionAction) () -> new FileReader("/etc/release")))) { + return in.readLine().trim().split(" ")[2]; + } catch (PrivilegedActionException e) { + System.out.println("Second attempt failed with: " + e.getException().getMessage()); + } catch (Exception e) { + System.out.println("Second attempt failed with: " + e.getMessage()); + } + + throw new RuntimeException("Unable to get Solaris version"); + } + + @Override + public int compareTo(OSVersion o) { + return Arrays.compare(this.versionTokens, o.versionTokens); + } + + @Override + public int hashCode() { + return Arrays.hashCode(versionTokens); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + OSVersion osVersion = (OSVersion) o; + return Arrays.equals(versionTokens, osVersion.versionTokens); + } + + @Override + public String toString() { + return Arrays.stream(versionTokens) + .mapToObj(String::valueOf) + .collect(Collectors.joining(".")); + } +} + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/Platform.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/Platform.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.regex.Pattern; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +public class Platform { + public static final String vmName = privilegedGetProperty("java.vm.name"); + public static final String vmInfo = privilegedGetProperty("java.vm.info"); + private static final String osVersion = privilegedGetProperty("os.version"); + private static int osVersionMajor = -1; + private static int osVersionMinor = -1; + private static final String osName = privilegedGetProperty("os.name"); + private static final String dataModel = privilegedGetProperty("sun.arch.data.model"); + private static final String vmVersion = privilegedGetProperty("java.vm.version"); + private static final String jdkDebug = privilegedGetProperty("jdk.debug"); + private static final String osArch = privilegedGetProperty("os.arch"); + private static final String userName = privilegedGetProperty("user.name"); + private static final String compiler = privilegedGetProperty("sun.management.compiler"); + + private static String privilegedGetProperty(String key) { + return AccessController.doPrivileged(( + PrivilegedAction) () -> System.getProperty(key)); + } + + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } + + public static boolean isGraal() { + return vmName.endsWith(" Graal VM"); + } + + public static boolean isZero() { + return vmName.endsWith(" Zero VM"); + } + + public static boolean isMinimal() { + return vmName.endsWith(" Minimal VM"); + } + + public static boolean isEmbedded() { + return vmName.contains("Embedded"); + } + + public static boolean isEmulatedClient() { + return vmInfo.contains(" emulated-client"); + } + + public static boolean isTieredSupported() { + return compiler.contains("Tiered Compilers"); + } + + public static boolean isInt() { + return vmInfo.contains("interpreted"); + } + + public static boolean isMixed() { + return vmInfo.contains("mixed"); + } + + public static boolean isComp() { + return vmInfo.contains("compiled"); + } + + public static boolean is32bit() { + return dataModel.equals("32"); + } + + public static boolean is64bit() { + return dataModel.equals("64"); + } + + public static boolean isAix() { + return isOs("aix"); + } + + public static boolean isLinux() { + return isOs("linux"); + } + + public static boolean isOSX() { + return isOs("mac"); + } + + public static boolean isSolaris() { + return isOs("sunos"); + } + + public static boolean isWindows() { + return isOs("win"); + } + + private static boolean isOs(String osname) { + return osName.toLowerCase().startsWith(osname.toLowerCase()); + } + + public static String getOsName() { + return osName; + } + + // Os version support. + private static void init_version() { + String[] osVersionTokens = osVersion.split("\\."); + try { + if (osVersionTokens.length > 0) { + osVersionMajor = Integer.parseInt(osVersionTokens[0]); + if (osVersionTokens.length > 1) { + osVersionMinor = Integer.parseInt(osVersionTokens[1]); + } + } + } catch (NumberFormatException e) { + osVersionMajor = osVersionMinor = 0; + } + } + + public static String getOsVersion() { + return osVersion; + } + + // Returns major version number from os.version system property. + // E.g. 5 on Solaris 10 and 3 on SLES 11.3 (for the linux kernel version). + public static int getOsVersionMajor() { + if (osVersionMajor == -1) init_version(); + return osVersionMajor; + } + + // Returns minor version number from os.version system property. + // E.g. 10 on Solaris 10 and 0 on SLES 11.3 (for the linux kernel version). + public static int getOsVersionMinor() { + if (osVersionMinor == -1) init_version(); + return osVersionMinor; + } + + public static boolean isDebugBuild() { + return (jdkDebug.toLowerCase().contains("debug")); + } + + public static boolean isSlowDebugBuild() { + return (jdkDebug.toLowerCase().equals("slowdebug")); + } + + public static boolean isFastDebugBuild() { + return (jdkDebug.toLowerCase().equals("fastdebug")); + } + + public static String getVMVersion() { + return vmVersion; + } + + public static boolean isAArch64() { + return isArch("aarch64"); + } + + public static boolean isARM() { + return isArch("arm.*"); + } + + public static boolean isPPC() { + return isArch("ppc.*"); + } + + // Returns true for IBM z System running linux. + public static boolean isS390x() { + return isArch("s390.*") || isArch("s/390.*") || isArch("zArch_64"); + } + + // Returns true for sparc and sparcv9. + public static boolean isSparc() { + return isArch("sparc.*"); + } + + public static boolean isX64() { + // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64' + return isArch("(amd64)|(x86_64)"); + } + + public static boolean isX86() { + // On Linux it's 'i386', Windows 'x86' without '_64' suffix. + return isArch("(i386)|(x86(?!_64))"); + } + + public static String getOsArch() { + return osArch; + } + + /** + * Return a boolean for whether SA and jhsdb are ported/available + * on this platform. + */ + public static boolean hasSA() { + if (isAix()) { + return false; // SA not implemented. + } else if (isLinux()) { + if (isS390x() || isARM()) { + return false; // SA not implemented. + } + } + // Other platforms expected to work: + return true; + } + + /** + * Return a boolean for whether we expect to be able to attach + * the SA to our own processes on this system. This requires + * that SA is ported/available on this platform. + */ + public static boolean shouldSAAttach() throws IOException { + if (!hasSA()) return false; + if (isLinux()) { + return canPtraceAttachLinux(); + } else if (isOSX()) { + return canAttachOSX(); + } else { + // Other platforms expected to work: + return true; + } + } + + /** + * On Linux, first check the SELinux boolean "deny_ptrace" and return false + * as we expect to be denied if that is "1". Then expect permission to attach + * if we are root, so return true. Then return false for an expected denial + * if "ptrace_scope" is 1, and true otherwise. + */ + private static boolean canPtraceAttachLinux() throws IOException { + // SELinux deny_ptrace: + File deny_ptrace = new File("/sys/fs/selinux/booleans/deny_ptrace"); + if (deny_ptrace.exists()) { + try (RandomAccessFile file = AccessController.doPrivileged( + (PrivilegedExceptionAction) () -> new RandomAccessFile(deny_ptrace, "r"))) { + if (file.readByte() != '0') { + return false; + } + } catch (PrivilegedActionException e) { + @SuppressWarnings("unchecked") + IOException t = (IOException) e.getException(); + throw t; + } + } + + // YAMA enhanced security ptrace_scope: + // 0 - a process can PTRACE_ATTACH to any other process running under the same uid + // 1 - restricted ptrace: a process must be a children of the inferior or user is root + // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root + // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH + File ptrace_scope = new File("/proc/sys/kernel/yama/ptrace_scope"); + if (ptrace_scope.exists()) { + try (RandomAccessFile file = AccessController.doPrivileged( + (PrivilegedExceptionAction) () -> new RandomAccessFile(ptrace_scope, "r"))) { + byte yama_scope = file.readByte(); + if (yama_scope == '3') { + return false; + } + + if (!userName.equals("root") && yama_scope != '0') { + return false; + } + } catch (PrivilegedActionException e) { + @SuppressWarnings("unchecked") + IOException t = (IOException) e.getException(); + throw t; + } + } + // Otherwise expect to be permitted: + return true; + } + + /** + * On OSX, expect permission to attach only if we are root. + */ + private static boolean canAttachOSX() { + return userName.equals("root"); + } + + private static boolean isArch(String archnameRE) { + return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE) + .matcher(osArch) + .matches(); + } + + /** + * Returns file extension of shared library, e.g. "so" on linux, "dll" on windows. + * @return file extension + */ + public static String sharedLibraryExt() { + if (isWindows()) { + return "dll"; + } else if (isOSX()) { + return "dylib"; + } else { + return "so"; + } + } + + /* + * Returns name of system variable containing paths to shared native libraries. + */ + public static String sharedLibraryPathVariableName() { + if (isWindows()) { + return "PATH"; + } else if (isOSX()) { + return "DYLD_LIBRARY_PATH"; + } else if (isAix()) { + return "LIBPATH"; + } else { + return "LD_LIBRARY_PATH"; + } + } + + public static boolean isDefaultCDSArchiveSupported() { + return (is64bit() && + isServer() && + (isLinux() || + isOSX() || + isSolaris() || + isWindows()) && + !isZero() && + !isMinimal() && + !isAArch64() && + !isARM()); + } + + /* + * This should match the #if condition in ClassListParser::load_class_from_source(). + */ + public static boolean areCustomLoadersSupportedForCDS() { + return (is64bit() && (isLinux() || isSolaris() || isOSX())); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/RandomFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/RandomFactory.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.Random; +import java.util.SplittableRandom; + +/** + * Factory class which generates and prints to STDOUT a long-valued seed + * for use in initializing a PRNG. An instance of {@code Random} or + * {@code SplittableRandom} may likewise be obtained. + */ +public class RandomFactory { + /** + * Attempt to obtain the seed from the value of the "seed" property. + * @return The seed or {@code null} if the "seed" property was not set or + * could not be parsed. + */ + private static Long getSystemSeed() { + Long seed = null; + try { + // note that Long.valueOf(null) also throws a + // NumberFormatException so if the property is undefined this + // will still work correctly + seed = Long.valueOf(System.getProperty("seed")); + } catch (NumberFormatException e) { + // do nothing: seed is still null + } + + return seed; + } + + /** + * Obtain a seed from an independent PRNG. + * + * @return A random seed. + */ + private static long getRandomSeed() { + return new Random().nextLong(); + } + + /** + * Obtain and print to STDOUT a seed appropriate for initializing a PRNG. + * If the system property "seed" is set and has value which may be correctly + * parsed it is used, otherwise a seed is generated using an independent + * PRNG. + * + * @return The seed. + */ + public static long getSeed() { + Long seed = getSystemSeed(); + if (seed == null) { + seed = getRandomSeed(); + } + System.out.println("Seed from RandomFactory = "+seed+"L"); + return seed; + } + + /** + * Obtain and print to STDOUT a seed and use it to initialize a new + * {@code Random} instance which is returned. If the system + * property "seed" is set and has value which may be correctly parsed it + * is used, otherwise a seed is generated using an independent PRNG. + * + * @return The {@code Random} instance. + */ + public static Random getRandom() { + return new Random(getSeed()); + } + + /** + * Obtain and print to STDOUT a seed and use it to initialize a new + * {@code SplittableRandom} instance which is returned. If the system + * property "seed" is set and has value which may be correctly parsed it + * is used, otherwise a seed is generated using an independent PRNG. + * + * @return The {@code SplittableRandom} instance. + */ + public static SplittableRandom getSplittableRandom() { + return new SplittableRandom(getSeed()); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/SecurityTools.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/SecurityTools.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,279 @@ +/* + * 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 jdk.test.lib; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/** + * Run security tools (including jarsigner and keytool) in a new process. + * The en_US locale is always used so a test can always match output to + * English text. {@code /dev/urandom} is used as entropy source so tool will + * not block because of entropy scarcity. {@code -Jvm-options} is supported + * as an argument. + */ +public class SecurityTools { + + /** + * The response file name for keytool. Use {@link #setResponse} to + * create one. Do NOT manipulate it directly. + */ + public static final String RESPONSE_FILE = "security_tools_response.txt"; + + private SecurityTools() {} + + public static ProcessBuilder getProcessBuilder(String tool, List args) { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(tool) + .addVMArg("-Duser.language=en") + .addVMArg("-Duser.country=US"); + if (!Platform.isWindows()) { + launcher.addVMArg("-Djava.security.egd=file:/dev/./urandom"); + } + for (String arg : args) { + if (arg.startsWith("-J")) { + launcher.addVMArg(arg.substring(2)); + } else if (Platform.isWindows() && arg.isEmpty()) { + // JDK-6518827: special handling for empty argument on Windows + launcher.addToolArg("\"\""); + } else { + launcher.addToolArg(arg); + } + } + return new ProcessBuilder(launcher.getCommand()); + } + + /** + * Runs keytool. + * + * @param args arguments to keytool + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer keytool(List args) + throws Exception { + + ProcessBuilder pb = getProcessBuilder("keytool", args); + + Path p = Paths.get(RESPONSE_FILE); + if (!Files.exists(p)) { + Files.createFile(p); + } + pb.redirectInput(ProcessBuilder.Redirect.from(new File(RESPONSE_FILE))); + + try { + return execute(pb); + } finally { + Files.delete(p); + } + } + + /** + * Runs keytool. + * + * @param args arguments to keytool in a single string. The string is + * converted to be List with makeList. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer keytool(String args) throws Exception { + return keytool(makeList(args)); + } + + /** + * Runs keytool. + * + * @param args arguments to keytool + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer keytool(String... args) throws Exception { + return keytool(List.of(args)); + } + + + /** + * Sets the responses (user input) for keytool. + *

+ * For example, if keytool requires entering a password twice, call + * {@code setResponse("password", "password")}. Do NOT append a newline + * character to each response. If there are useless responses at the end, + * they will be discarded silently. If there are less responses than + * necessary, keytool will read EOF. The responses will be written into + * {@linkplain #RESPONSE_FILE a local file} and will only be used by the + * next keytool run. After the run, the file is removed. Calling this + * method will always overwrite the previous response file (if exists). + * + * @param responses response to keytool + * @throws IOException if there is an error + */ + public static void setResponse(String... responses) throws IOException { + String text; + if (responses.length > 0) { + text = Stream.of(responses).collect( + Collectors.joining("\n", "", "\n")); + } else { + text = ""; + } + Files.write(Paths.get(RESPONSE_FILE), text.getBytes()); + } + + /** + * Runs jarsigner. + * + * @param args arguments to jarsigner + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jarsigner(List args) + throws Exception { + return execute(getProcessBuilder("jarsigner", args)); + } + + private static OutputAnalyzer execute(ProcessBuilder pb) throws Exception { + try { + OutputAnalyzer oa = ProcessTools.executeCommand(pb); + System.out.println("Exit value: " + oa.getExitValue()); + return oa; + } catch (Throwable t) { + if (t instanceof Exception) { + throw (Exception) t; + } else { + throw new Exception(t); + } + } + } + + /** + * Runs jarsigner. + * + * @param args arguments to jarsigner in a single string. The string is + * converted to be List with makeList. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jarsigner(String args) throws Exception { + + return jarsigner(makeList(args)); + } + + /** + * Runs jarsigner. + * + * @param args arguments to jarsigner + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jarsigner(String... args) throws Exception { + return jarsigner(List.of(args)); + } + + /** + * Runs ktab. + * + * @param args arguments to ktab in a single string. The string is + * converted to be List with makeList. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer ktab(String args) throws Exception { + return execute(getProcessBuilder("ktab", makeList(args))); + } + + /** + * Runs klist. + * + * @param args arguments to klist in a single string. The string is + * converted to be List with makeList. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer klist(String args) throws Exception { + return execute(getProcessBuilder("klist", makeList(args))); + } + + /** + * Runs jar. + * + * @param args arguments to jar in a single string. The string is + * converted to be List with makeList. + * @return an {@link OutputAnalyzer} object + * @throws Exception if there is an error + */ + public static OutputAnalyzer jar(String args) throws Exception { + return execute(getProcessBuilder("jar", makeList(args))); + } + + /** + * Split a line to a list of string. All whitespaces are treated as + * delimiters unless quoted between ` and `. + * + * @param line the input + * @return the list + */ + public static List makeList(String line) { + List result = new ArrayList<>(); + StringBuilder sb = new StringBuilder(); + boolean inBackTick = false; + for (char c : line.toCharArray()) { + if (inBackTick) { + if (c == '`') { + result.add(sb.toString()); + sb.setLength(0); + inBackTick = false; + } else { + sb.append(c); + } + } else { + if (sb.length() == 0 && c == '`') { + // Allow ` inside a string + inBackTick = true; + } else { + if (Character.isWhitespace(c)) { + if (sb.length() != 0) { + result.add(sb.toString()); + sb.setLength(0); + } + } else { + sb.append(c); + } + } + } + } + if (sb.length() != 0) { + result.add(sb.toString()); + } + return result; + } +} + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/SigTestUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/SigTestUtil.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,150 @@ +/* + * 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 jdk.test.lib; + +import java.security.*; +import java.security.spec.*; +import java.util.*; + +/* + * Utility class used by various Signature related regression tests for + * common functions such as generating the list of to-be-tested algorithms + * based on key size, etc. Currently, this is mostly needed by RSA + * signatures. + */ +public class SigTestUtil { + + public enum SignatureType { + RSA("RSA"), + RSASSA_PSS("RSASSA-PSS") + ; + + private String keyAlg; + + SignatureType(String keyAlg) { + this.keyAlg = keyAlg; + } + @Override + public String toString() { + return keyAlg; + } + } + + // collection of all supported digest algorithms + // note that the entries are ordered by required key sizes + private static final String[] DIGEST_ALGS = { + "SHA-512", + "SHA-384", + "SHA-256", + "SHA-512/256", + "SHA-224", + "SHA-512/224", + "SHA-1", + "MD2", "MD5" // these aren't supported by RSA PSS + }; + + // indice for message digest algorithms lookup + // may need to be adjusted if new algorithms are added + private static final int PKCS1_5_INDEX_768 = 0; + private static final int PKCS1_5_INDEX_512 = 2; + private static final int PKCS1_5_INDEX_END = DIGEST_ALGS.length; + private static final int PSS_INDEX_2048 = 0; + private static final int PSS_INDEX_1024 = 1; + private static final int PSS_INDEX_768 = 2; + private static final int PSS_INDEX_512 = 4; + private static final int PSS_INDEX_END = 7; + + public static Iterable getDigestAlgorithms(SignatureType type, + int keysize) throws RuntimeException { + + // initialize to all, then trim based on key size + List result = new ArrayList<>(Arrays.asList(DIGEST_ALGS)); + int index = 0; + switch (type) { + case RSA: + if (keysize >= 768) { + index = PKCS1_5_INDEX_768; + } else if (keysize >= 512) { + index = PKCS1_5_INDEX_512; + } else { + throw new RuntimeException("Keysize too small: " + keysize); + } + result = result.subList(index, PKCS1_5_INDEX_END); + break; + case RSASSA_PSS: + if (keysize >= 2048) { + index = PSS_INDEX_2048; + } else if (keysize >= 1024) { + index = PSS_INDEX_1024; + } else if (keysize >= 768) { + index = PSS_INDEX_768; + } else if (keysize >= 512) { + index = PSS_INDEX_512; + } else { + throw new RuntimeException("Keysize too small: " + keysize); + } + result = result.subList(index, PSS_INDEX_END); + break; + default: + // XXX maybe just return result instead of error out? + throw new RuntimeException("Unsupported signature type: " + type); + } + return result; + } + + public static AlgorithmParameterSpec generateDefaultParameter( + SignatureType type, String mdAlg) throws RuntimeException { + // only RSASSA-PSS signature uses parameters + switch (type) { + case RSASSA_PSS: + try { + MessageDigest md = MessageDigest.getInstance(mdAlg); + return new PSSParameterSpec(mdAlg, "MGF1", + new MGF1ParameterSpec(mdAlg), md.getDigestLength(), + PSSParameterSpec.TRAILER_FIELD_BC); + } catch (Exception e) { + throw new RuntimeException(e); + } + default: + return null; + } + } + + public static String generateSigAlg(SignatureType type, + String mdAlg) throws RuntimeException { + switch (type) { + case RSA: + int idx = mdAlg.indexOf("-"); + if (idx != -1) { + mdAlg = mdAlg.substring(0, idx) + mdAlg.substring(idx+1); + } + return mdAlg + "with" + type.toString(); + case RSASSA_PSS: + return type.toString(); + default: + throw new RuntimeException("Unsupported signature type " + type ); + } + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/TimeLimitedRunner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/TimeLimitedRunner.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.util.Objects; +import java.util.concurrent.Callable; + +/** + * Auxiliary class to run target w/ given timeout. + */ +public class TimeLimitedRunner implements Callable { + private final long stoptime; + private final long timeout; + private final double factor; + private final Callable target; + + /** + * @param timeout a timeout. zero means no time limitation + * @param factor a multiplier used to estimate next iteration time + * @param target a target to run + * @throws NullPointerException if target is null + * @throws IllegalArgumentException if timeout is negative or + factor isn't positive + */ + public TimeLimitedRunner(long timeout, double factor, + Callable target) { + Objects.requireNonNull(target, "target must not be null"); + if (timeout < 0) { + throw new IllegalArgumentException("timeout[" + timeout + "] < 0"); + } + if (factor <= 0d) { + throw new IllegalArgumentException("factor[" + factor + "] <= 0"); + } + this.stoptime = System.currentTimeMillis() + timeout; + this.timeout = timeout; + this.factor = factor; + this.target = target; + } + + /** + * Runs @{linkplan target} while it returns true and timeout isn't exceeded + */ + @Override + public Void call() throws Exception { + long maxDuration = 0L; + long iterStart = System.currentTimeMillis(); + if (timeout != 0 && iterStart > stoptime) { + return null; + } + while (target.call()) { + if (timeout != 0) { + long iterDuration = System.currentTimeMillis() - iterStart; + maxDuration = Math.max(maxDuration, iterDuration); + iterStart = System.currentTimeMillis(); + if (iterStart + (maxDuration * factor) > stoptime) { + System.out.println("Not enough time to continue execution. " + + "Interrupted."); + break; + } + } + } + return null; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/Utils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/Utils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,818 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.File; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.ServerSocket; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileAttribute; +import java.nio.channels.SocketChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.Random; +import java.util.function.BooleanSupplier; +import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static jdk.test.lib.Asserts.assertTrue; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +/** + * Common library for various test helper functions. + */ +public final class Utils { + + /** + * Returns the value of 'test.class.path' system property. + */ + public static final String TEST_CLASS_PATH = System.getProperty("test.class.path", "."); + + /** + * Returns the sequence used by operating system to separate lines. + */ + public static final String NEW_LINE = System.getProperty("line.separator"); + + /** + * Returns the value of 'test.vm.opts' system property. + */ + public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim(); + + /** + * Returns the value of 'test.java.opts' system property. + */ + public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim(); + + /** + * Returns the value of 'test.src' system property. + */ + public static final String TEST_SRC = System.getProperty("test.src", "").trim(); + + /** + * Returns the value of 'test.root' system property. + */ + public static final String TEST_ROOT = System.getProperty("test.root", "").trim(); + + /* + * Returns the value of 'test.jdk' system property + */ + public static final String TEST_JDK = System.getProperty("test.jdk"); + + /* + * Returns the value of 'compile.jdk' system property + */ + public static final String COMPILE_JDK = System.getProperty("compile.jdk", TEST_JDK); + + /** + * Returns the value of 'test.classes' system property + */ + public static final String TEST_CLASSES = System.getProperty("test.classes", "."); + + /** + * Defines property name for seed value. + */ + public static final String SEED_PROPERTY_NAME = "jdk.test.lib.random.seed"; + + /* (non-javadoc) + * Random generator with (or without) predefined seed. Depends on + * "jdk.test.lib.random.seed" property value. + */ + private static volatile Random RANDOM_GENERATOR; + + /** + * Contains the seed value used for {@link java.util.Random} creation. + */ + public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong()); + /** + * Returns the value of 'test.timeout.factor' system property + * converted to {@code double}. + */ + public static final double TIMEOUT_FACTOR; + static { + String toFactor = System.getProperty("test.timeout.factor", "1.0"); + TIMEOUT_FACTOR = Double.parseDouble(toFactor); + } + + /** + * Returns the value of JTREG default test timeout in milliseconds + * converted to {@code long}. + */ + public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + + private Utils() { + // Private constructor to prevent class instantiation + } + + /** + * Returns the list of VM options. + * + * @return List of VM options + */ + public static List getVmOptions() { + return Arrays.asList(safeSplitString(VM_OPTIONS)); + } + + /** + * Returns the list of VM options with -J prefix. + * + * @return The list of VM options with -J prefix + */ + public static List getForwardVmOptions() { + String[] opts = safeSplitString(VM_OPTIONS); + for (int i = 0; i < opts.length; i++) { + opts[i] = "-J" + opts[i]; + } + return Arrays.asList(opts); + } + + /** + * Returns the default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @return An array of options, or an empty array if no options. + */ + public static String[] getTestJavaOpts() { + List opts = new ArrayList(); + Collections.addAll(opts, safeSplitString(VM_OPTIONS)); + Collections.addAll(opts, safeSplitString(JAVA_OPTIONS)); + return opts.toArray(new String[0]); + } + + /** + * Combines given arguments with default JTReg arguments for a jvm running a test. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts + * @return The combination of JTReg test java options and user args. + */ + public static String[] addTestJavaOpts(String... userArgs) { + List opts = new ArrayList(); + Collections.addAll(opts, getTestJavaOpts()); + Collections.addAll(opts, userArgs); + return opts.toArray(new String[0]); + } + + /** + * Removes any options specifying which GC to use, for example "-XX:+UseG1GC". + * Removes any options matching: -XX:(+/-)Use*GC + * Used when a test need to set its own GC version. Then any + * GC specified by the framework must first be removed. + * @return A copy of given opts with all GC options removed. + */ + private static final Pattern useGcPattern = Pattern.compile( + "(?:\\-XX\\:[\\+\\-]Use.+GC)" + + "|(?:\\-Xconcgc)"); + public static List removeGcOpts(List opts) { + List optsWithoutGC = new ArrayList(); + for (String opt : opts) { + if (useGcPattern.matcher(opt).matches()) { + System.out.println("removeGcOpts: removed " + opt); + } else { + optsWithoutGC.add(opt); + } + } + return optsWithoutGC; + } + + /** + * Returns the default JTReg arguments for a jvm running a test without + * options that matches regular expressions in {@code filters}. + * This is the combination of JTReg arguments test.vm.opts and test.java.opts. + * @param filters Regular expressions used to filter out options. + * @return An array of options, or an empty array if no options. + */ + public static String[] getFilteredTestJavaOpts(String... filters) { + String options[] = getTestJavaOpts(); + + if (filters.length == 0) { + return options; + } + + List filteredOptions = new ArrayList(options.length); + Pattern patterns[] = new Pattern[filters.length]; + for (int i = 0; i < filters.length; i++) { + patterns[i] = Pattern.compile(filters[i]); + } + + for (String option : options) { + boolean matched = false; + for (int i = 0; i < patterns.length && !matched; i++) { + Matcher matcher = patterns[i].matcher(option); + matched = matcher.find(); + } + if (!matched) { + filteredOptions.add(option); + } + } + + return filteredOptions.toArray(new String[filteredOptions.size()]); + } + + /** + * Splits a string by white space. + * Works like String.split(), but returns an empty array + * if the string is null or empty. + */ + private static String[] safeSplitString(String s) { + if (s == null || s.trim().isEmpty()) { + return new String[] {}; + } + return s.trim().split("\\s+"); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString(); + } + + /** + * Returns the socket address of an endpoint that refuses connections. The + * endpoint is an InetSocketAddress where the address is the loopback address + * and the port is a system port (1-1023 range). + * This method is a better choice than getFreePort for tests that need + * an endpoint that refuses connections. + */ + public static InetSocketAddress refusingEndpoint() { + InetAddress lb = InetAddress.getLoopbackAddress(); + int port = 1; + while (port < 1024) { + InetSocketAddress sa = new InetSocketAddress(lb, port); + try { + SocketChannel.open(sa).close(); + } catch (IOException ioe) { + return sa; + } + port++; + } + throw new RuntimeException("Unable to find system port that is refusing connections"); + } + + /** + * Returns the free port on the local host. + * + * @return The port number + * @throws IOException if an I/O error occurs when opening the socket + */ + public static int getFreePort() throws IOException { + try (ServerSocket serverSocket = + new ServerSocket(0, 5, InetAddress.getLoopbackAddress());) { + return serverSocket.getLocalPort(); + } + } + + /** + * Returns the name of the local host. + * + * @return The host name + * @throws UnknownHostException if IP address of a host could not be determined + */ + public static String getHostname() throws UnknownHostException { + InetAddress inetAddress = InetAddress.getLocalHost(); + String hostName = inetAddress.getHostName(); + + assertTrue((hostName != null && !hostName.isEmpty()), + "Cannot get hostname"); + + return hostName; + } + + /** + * Uses "jcmd -l" to search for a jvm pid. This function will wait + * forever (until jtreg timeout) for the pid to be found. + * @param key Regular expression to search for + * @return The found pid. + */ + public static int waitForJvmPid(String key) throws Throwable { + final long iterationSleepMillis = 250; + System.out.println("waitForJvmPid: Waiting for key '" + key + "'"); + System.out.flush(); + while (true) { + int pid = tryFindJvmPid(key); + if (pid >= 0) { + return pid; + } + Thread.sleep(iterationSleepMillis); + } + } + + /** + * Searches for a jvm pid in the output from "jcmd -l". + * + * Example output from jcmd is: + * 12498 sun.tools.jcmd.JCmd -l + * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar + * + * @param key A regular expression to search for. + * @return The found pid, or -1 if not found. + * @throws Exception If multiple matching jvms are found. + */ + public static int tryFindJvmPid(String key) throws Throwable { + OutputAnalyzer output = null; + try { + JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd"); + jcmdLauncher.addToolArg("-l"); + output = ProcessTools.executeProcess(jcmdLauncher.getCommand()); + output.shouldHaveExitValue(0); + + // Search for a line starting with numbers (pid), follwed by the key. + Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n"); + Matcher matcher = pattern.matcher(output.getStdout()); + + int pid = -1; + if (matcher.find()) { + pid = Integer.parseInt(matcher.group(1)); + System.out.println("findJvmPid.pid: " + pid); + if (matcher.find()) { + throw new Exception("Found multiple JVM pids for key: " + key); + } + } + return pid; + } catch (Throwable t) { + System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t)); + throw t; + } + } + + /** + * Adjusts the provided timeout value for the TIMEOUT_FACTOR + * @param tOut the timeout value to be adjusted + * @return The timeout value adjusted for the value of "test.timeout.factor" + * system property + */ + public static long adjustTimeout(long tOut) { + return Math.round(tOut * Utils.TIMEOUT_FACTOR); + } + + /** + * Return the contents of the named file as a single String, + * or null if not found. + * @param filename name of the file to read + * @return String contents of file, or null if file not found. + * @throws IOException + * if an I/O error occurs reading from the file or a malformed or + * unmappable byte sequence is read + */ + public static String fileAsString(String filename) throws IOException { + Path filePath = Paths.get(filename); + if (!Files.exists(filePath)) return null; + return new String(Files.readAllBytes(filePath)); + } + + private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /** + * Returns hex view of byte array + * + * @param bytes byte array to process + * @return space separated hexadecimal string representation of bytes + */ + public static String toHexString(byte[] bytes) { + char[] hexView = new char[bytes.length * 3 - 1]; + for (int i = 0; i < bytes.length - 1; i++) { + hexView[i * 3] = hexArray[(bytes[i] >> 4) & 0x0F]; + hexView[i * 3 + 1] = hexArray[bytes[i] & 0x0F]; + hexView[i * 3 + 2] = ' '; + } + hexView[hexView.length - 2] = hexArray[(bytes[bytes.length - 1] >> 4) & 0x0F]; + hexView[hexView.length - 1] = hexArray[bytes[bytes.length - 1] & 0x0F]; + return new String(hexView); + } + + /** + * Returns byte array of hex view + * + * @param hex hexadecimal string representation + * @return byte array + */ + public static byte[] toByteArray(String hex) { + int length = hex.length(); + byte[] bytes = new byte[length / 2]; + for (int i = 0; i < length; i += 2) { + bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + + Character.digit(hex.charAt(i + 1), 16)); + } + return bytes; + } + + /** + * Returns {@link java.util.Random} generator initialized with particular seed. + * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME} + * In case no seed is provided, the method uses a random number. + * The used seed printed to stdout. + * @return {@link java.util.Random} generator with particular seed. + */ + public static Random getRandomInstance() { + if (RANDOM_GENERATOR == null) { + synchronized (Utils.class) { + if (RANDOM_GENERATOR == null) { + RANDOM_GENERATOR = new Random(SEED); + System.out.printf("For random generator using seed: %d%n", SEED); + System.out.printf("To re-run test with same seed value please add \"-D%s=%d\" to command line.%n", SEED_PROPERTY_NAME, SEED); + } + } + } + return RANDOM_GENERATOR; + } + + /** + * Returns random element of non empty collection + * + * @param a type of collection element + * @param collection collection of elements + * @return random element of collection + * @throws IllegalArgumentException if collection is empty + */ + public static T getRandomElement(Collection collection) + throws IllegalArgumentException { + if (collection.isEmpty()) { + throw new IllegalArgumentException("Empty collection"); + } + Random random = getRandomInstance(); + int elementIndex = 1 + random.nextInt(collection.size() - 1); + Iterator iterator = collection.iterator(); + while (--elementIndex != 0) { + iterator.next(); + } + return iterator.next(); + } + + /** + * Returns random element of non empty array + * + * @param a type of array element + * @param array array of elements + * @return random element of array + * @throws IllegalArgumentException if array is empty + */ + public static T getRandomElement(T[] array) + throws IllegalArgumentException { + if (array == null || array.length == 0) { + throw new IllegalArgumentException("Empty or null array"); + } + Random random = getRandomInstance(); + return array[random.nextInt(array.length)]; + } + + /** + * Wait for condition to be true + * + * @param condition, a condition to wait for + */ + public static final void waitForCondition(BooleanSupplier condition) { + waitForCondition(condition, -1L, 100L); + } + + /** + * Wait until timeout for condition to be true + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true + * specifying -1 will wait forever + * @return condition value, to determine if wait was successful + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout) { + return waitForCondition(condition, timeout, 100L); + } + + /** + * Wait until timeout for condition to be true for specified time + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true, + * specifying -1 will wait forever + * @param sleepTime a time to sleep value in milliseconds + * @return condition value, to determine if wait was successful + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout, long sleepTime) { + long startTime = System.currentTimeMillis(); + while (!(condition.getAsBoolean() || (timeout != -1L + && ((System.currentTimeMillis() - startTime) > timeout)))) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } + return condition.getAsBoolean(); + } + + /** + * Interface same as java.lang.Runnable but with + * method {@code run()} able to throw any Throwable. + */ + public static interface ThrowingRunnable { + void run() throws Throwable; + } + + /** + * Filters out an exception that may be thrown by the given + * test according to the given filter. + * + * @param test - method that is invoked and checked for exception. + * @param filter - function that checks if the thrown exception matches + * criteria given in the filter's implementation. + * @return - exception that matches the filter if it has been thrown or + * {@code null} otherwise. + * @throws Throwable - if test has thrown an exception that does not + * match the filter. + */ + public static Throwable filterException(ThrowingRunnable test, + Function filter) throws Throwable { + try { + test.run(); + } catch (Throwable t) { + if (filter.apply(t)) { + return t; + } else { + throw t; + } + } + return null; + } + + /** + * Ensures a requested class is loaded + * @param aClass class to load + */ + public static void ensureClassIsLoaded(Class aClass) { + if (aClass == null) { + throw new Error("Requested null class"); + } + try { + Class.forName(aClass.getName(), /* initialize = */ true, + ClassLoader.getSystemClassLoader()); + } catch (ClassNotFoundException e) { + throw new Error("Class not found", e); + } + } + /** + * @param parent a class loader to be the parent for the returned one + * @return an UrlClassLoader with urls made of the 'test.class.path' jtreg + * property and with the given parent + */ + public static URLClassLoader getTestClassPathURLClassLoader(ClassLoader parent) { + URL[] urls = Arrays.stream(TEST_CLASS_PATH.split(File.pathSeparator)) + .map(Paths::get) + .map(Path::toUri) + .map(x -> { + try { + return x.toURL(); + } catch (MalformedURLException ex) { + throw new Error("Test issue. JTREG property" + + " 'test.class.path'" + + " is not defined correctly", ex); + } + }).toArray(URL[]::new); + return new URLClassLoader(urls, parent); + } + + /** + * Runs runnable and checks that it throws expected exception. If exceptionException is null it means + * that we expect no exception to be thrown. + * @param runnable what we run + * @param expectedException expected exception + */ + public static void runAndCheckException(ThrowingRunnable runnable, Class expectedException) { + runAndCheckException(runnable, t -> { + if (t == null) { + if (expectedException != null) { + throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName()); + } + } else { + String message = "Got unexpected exception " + t.getClass().getSimpleName(); + if (expectedException == null) { + throw new AssertionError(message, t); + } else if (!expectedException.isAssignableFrom(t.getClass())) { + message += " instead of " + expectedException.getSimpleName(); + throw new AssertionError(message, t); + } + } + }); + } + + /** + * Runs runnable and makes some checks to ensure that it throws expected exception. + * @param runnable what we run + * @param checkException a consumer which checks that we got expected exception and raises a new exception otherwise + */ + public static void runAndCheckException(ThrowingRunnable runnable, Consumer checkException) { + Throwable throwable = null; + try { + runnable.run(); + } catch (Throwable t) { + throwable = t; + } + checkException.accept(throwable); + } + + /** + * Converts to VM type signature + * + * @param type Java type to convert + * @return string representation of VM type + */ + public static String toJVMTypeSignature(Class type) { + if (type.isPrimitive()) { + if (type == boolean.class) { + return "Z"; + } else if (type == byte.class) { + return "B"; + } else if (type == char.class) { + return "C"; + } else if (type == double.class) { + return "D"; + } else if (type == float.class) { + return "F"; + } else if (type == int.class) { + return "I"; + } else if (type == long.class) { + return "J"; + } else if (type == short.class) { + return "S"; + } else if (type == void.class) { + return "V"; + } else { + throw new Error("Unsupported type: " + type); + } + } + String result = type.getName().replaceAll("\\.", "/"); + if (!type.isArray()) { + return "L" + result + ";"; + } + return result; + } + + public static Object[] getNullValues(Class... types) { + Object[] result = new Object[types.length]; + int i = 0; + for (Class type : types) { + result[i++] = NULL_VALUES.get(type); + } + return result; + } + private static Map, Object> NULL_VALUES = new HashMap<>(); + static { + NULL_VALUES.put(boolean.class, false); + NULL_VALUES.put(byte.class, (byte) 0); + NULL_VALUES.put(short.class, (short) 0); + NULL_VALUES.put(char.class, '\0'); + NULL_VALUES.put(int.class, 0); + NULL_VALUES.put(long.class, 0L); + NULL_VALUES.put(float.class, 0.0f); + NULL_VALUES.put(double.class, 0.0d); + } + + /** + * Returns mandatory property value + * @param propName is a name of property to request + * @return a String with requested property value + */ + public static String getMandatoryProperty(String propName) { + Objects.requireNonNull(propName, "Requested null property"); + String prop = System.getProperty(propName); + Objects.requireNonNull(prop, + String.format("A mandatory property '%s' isn't set", propName)); + return prop; + } + + /* + * Run uname with specified arguments. + */ + public static OutputAnalyzer uname(String... args) throws Throwable { + String[] cmds = new String[args.length + 1]; + cmds[0] = "uname"; + System.arraycopy(args, 0, cmds, 1, args.length); + return ProcessTools.executeCommand(cmds); + } + + /* + * Returns the system distro. + */ + public static String distro() { + try { + return uname("-v").asLines().get(0); + } catch (Throwable t) { + throw new RuntimeException("Failed to determine distro.", t); + } + } + + // This method is intended to be called from a jtreg test. + // It will identify the name of the test by means of stack walking. + // It can handle both jtreg tests and a testng tests wrapped inside jtreg tests. + // For jtreg tests the name of the test will be searched by stack-walking + // until the method main() is found; the class containing that method is the + // main test class and will be returned as the name of the test. + // Special handling is used for testng tests. + public static String getTestName() { + String result = null; + // If we are using testng, then we should be able to load the "Test" annotation. + Class testClassAnnotation; + + try { + testClassAnnotation = Class.forName("org.testng.annotations.Test"); + } catch (ClassNotFoundException e) { + testClassAnnotation = null; + } + + StackTraceElement[] elms = (new Throwable()).getStackTrace(); + for (StackTraceElement n: elms) { + String className = n.getClassName(); + + // If this is a "main" method, then use its class name, but only + // if we are not using testng. + if (testClassAnnotation == null && "main".equals(n.getMethodName())) { + result = className; + break; + } + + // If this is a testng test, the test will have no "main" method. We can + // detect a testng test class by looking for the org.testng.annotations.Test + // annotation. If present, then use the name of this class. + if (testClassAnnotation != null) { + try { + Class c = Class.forName(className); + if (c.isAnnotationPresent(testClassAnnotation)) { + result = className; + break; + } + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unexpected exception: " + e, e); + } + } + } + + if (result == null) { + throw new RuntimeException("Couldn't find main test class in stack trace"); + } + + return result; + } + + /** + * Creates an empty file in "user.dir" if the property set. + *

+ * This method is meant as a replacement for {@code Files#createTempFile(String, String, FileAttribute...)} + * that doesn't leave files behind in /tmp directory of the test machine + *

+ * If the property "user.dir" is not set, "." will be used. + * + * @param prefix + * @param suffix + * @param attrs + * @return the path to the newly created file that did not exist before this + * method was invoked + * @throws IOException + * + * @see {@link Files#createTempFile(String, String, FileAttribute...)} + */ + public static Path createTempFile(String prefix, String suffix, FileAttribute... attrs) throws IOException { + Path dir = Paths.get(System.getProperty("user.dir", ".")); + return Files.createTempFile(dir, prefix, suffix); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/Artifact.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/Artifact.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Repeatable(ArtifactContainer.class) +@Retention(RetentionPolicy.RUNTIME) +public @interface Artifact { + String organization(); + String name(); + String revision(); + String extension(); + String classifier() default ""; + boolean unpack() default true; +} + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/ArtifactContainer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/ArtifactContainer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface ArtifactContainer { + Artifact[] value(); +} + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/ArtifactManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/ArtifactManager.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.io.FileNotFoundException; +import java.nio.file.Path; + +public interface ArtifactManager { + public Path resolve(Artifact artifact) throws ArtifactResolverException; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/ArtifactResolver.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; + +public class ArtifactResolver { + public static Map resolve(Class klass) throws ArtifactResolverException { + ArtifactManager manager; + try { + String managerName = System.getProperty("jdk.test.lib.artifacts.artifactmanager"); + if (managerName != null) { + manager = (ArtifactManager) Class.forName(managerName).newInstance(); + } else if (System.getenv().containsKey(JibArtifactManager.JIB_HOME_ENV_NAME)) { + manager = JibArtifactManager.newInstance(); + } else { + manager = new DefaultArtifactManager(); + } + } catch (Exception e) { + throw new ArtifactResolverException("Failed to load ArtifactManager", e); + } + + ArtifactContainer artifactContainer = klass.getAnnotation(ArtifactContainer.class); + HashMap locations = new HashMap<>(); + Artifact[] artifacts; + + if (artifactContainer == null) { + artifacts = new Artifact[]{klass.getAnnotation(Artifact.class)}; + } else { + artifacts = artifactContainer.value(); + } + for (Artifact artifact : artifacts) { + locations.put(artifactName(artifact), manager.resolve(artifact)); + } + + return locations; + } + + private static String artifactName(Artifact artifact) { + // Format of the artifact name is .-(-) + String name = String.format("%s.%s-%s", artifact.organization(), artifact.name(), artifact.revision()); + if (artifact.classifier().length() != 0) { + name = name +"-" + artifact.classifier(); + } + return name; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/ArtifactResolverException.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,15 @@ +package jdk.test.lib.artifacts; + +/** + * Thrown by the ArtifactResolver when failing to resolve an Artifact. + */ +public class ArtifactResolverException extends Exception { + + public ArtifactResolverException(String message) { + super(message); + } + + public ArtifactResolverException(String message, Throwable cause) { + super(message, cause); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/DefaultArtifactManager.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class DefaultArtifactManager implements ArtifactManager { + @Override + public Path resolve(Artifact artifact) throws ArtifactResolverException { + String name = artifact.name(); + String location = System.getProperty(artifactProperty(name)); + if (location == null) { + throw new ArtifactResolverException("Couldn't automatically resolve dependency for " + name + + " , revision " + artifact.revision() + "\n" + + "Please specify the location using " + artifactProperty(name)); + } + return Paths.get(location); + } + + private static String artifactProperty(String name) { + return "jdk.test.lib.artifacts." + name; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/artifacts/JibArtifactManager.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.artifacts; + +import java.io.UncheckedIOException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public class JibArtifactManager implements ArtifactManager { + private static final String JIB_SERVICE_FACTORY = "com.oracle.jib.api.JibServiceFactory"; + public static final String JIB_HOME_ENV_NAME = "JIB_HOME"; + private static String jibVersion = "1.0"; + + private Object installerObject; + private ClassLoader classLoader; + + private JibArtifactManager(Object installerObject, ClassLoader classLoader) { + this.installerObject = installerObject; + this.classLoader = classLoader; + } + + public static JibArtifactManager newInstance() throws ClassNotFoundException { + Path jibInstallDir = Paths.get(System.getenv(JIB_HOME_ENV_NAME)); + Path libDir = jibInstallDir.resolve("lib"); + if (!Files.isDirectory(libDir)) { + throw new ClassNotFoundException(JIB_SERVICE_FACTORY); + } + try { + URL[] jarUrls; + try (Stream files = Files.list(libDir)) { + jarUrls = files.filter(path -> path.toString().endsWith(".jar")) + .map(path -> { + try { + return path.toUri().toURL(); + } catch (MalformedURLException e) { + throw new UncheckedIOException(e); + } + }).toArray(URL[]::new); + } + // Create a class loader using all those jars and set the parent to the + // current class loader's parent. + ClassLoader classLoader = new URLClassLoader(jarUrls, JibArtifactManager.class.getClassLoader().getParent()); + + // Temporarily replace the context classLoader + Thread currentThread = Thread.currentThread(); + ClassLoader oldContextLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(classLoader); + + Class jibServiceFactory = classLoader.loadClass(JIB_SERVICE_FACTORY); + try { + Object jibArtifactInstaller = jibServiceFactory.getMethod("createJibArtifactInstaller").invoke(null); + return new JibArtifactManager(jibArtifactInstaller, classLoader); + } finally { + currentThread.setContextClassLoader(oldContextLoader); + } + + } catch (Exception e) { + throw new ClassNotFoundException(JIB_SERVICE_FACTORY, e); + } + } + + private Path download(String jibVersion, HashMap artifactDescription) throws Exception { + return invokeInstallerMethod("download", jibVersion, artifactDescription); + } + + private Path install(String jibVersion, HashMap artifactDescription) throws Exception { + return invokeInstallerMethod("install", jibVersion, artifactDescription); + } + + private Path invokeInstallerMethod(String methodName, String jibVersion, + HashMap artifactDescription) throws Exception { + // Temporarily replace the context classLoader + Thread currentThread = Thread.currentThread(); + ClassLoader oldContextLoader = currentThread.getContextClassLoader(); + currentThread.setContextClassLoader(classLoader); + try { + Method m = classLoader.loadClass("com.oracle.jib.api.JibArtifactInstaller") + .getMethod(methodName, String.class, Map.class); + return (Path) m.invoke(installerObject, jibVersion, artifactDescription); + } finally { + currentThread.setContextClassLoader(oldContextLoader); + } + } + + @Override + public Path resolve(Artifact artifact) throws ArtifactResolverException { + Path path; + // Use the DefaultArtifactManager to enable users to override locations + try { + ArtifactManager manager = new DefaultArtifactManager(); + path = manager.resolve(artifact); + } catch (ArtifactResolverException e) { + // Location hasn't been overridden, continue to automatically try to resolve the dependency + try { + HashMap artifactDescription = new HashMap<>(); + artifactDescription.put("module", artifact.name()); + artifactDescription.put("organization", artifact.organization()); + artifactDescription.put("ext", artifact.extension()); + artifactDescription.put("revision", artifact.revision()); + if (artifact.classifier().length() > 0) { + artifactDescription.put("classifier", artifact.classifier()); + } + + path = download(jibVersion, artifactDescription); + if (artifact.unpack()) { + path = install(jibVersion, artifactDescription); + } + } catch (Exception e2) { + throw new ArtifactResolverException("Failed to resolve the artifact " + artifact, e2); + } + } + return path; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cds/CDSOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cds/CDSOptions.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,92 @@ +/* + * 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. + */ +package jdk.test.lib.cds; + +import java.util.ArrayList; + +// This class represents options used +// during creation of CDS archive and/or running JVM with a CDS archive +public class CDSOptions { + public String xShareMode = "on"; + public String archiveName; + public ArrayList prefix = new ArrayList(); + public ArrayList suffix = new ArrayList(); + public boolean useSystemArchive = false; + + // classes to be archived + public String[] classList; + + // Indicate whether to append "-version" when using CDS Archive. + // Most of tests will use '-version' + public boolean useVersion = true; + + + public CDSOptions() { + } + + + public CDSOptions addPrefix(String... prefix) { + for (String s : prefix) this.prefix.add(s); + return this; + } + + + public CDSOptions addSuffix(String... suffix) { + for (String s : suffix) this.suffix.add(s); + return this; + } + + public CDSOptions setXShareMode(String mode) { + this.xShareMode = mode; + return this; + } + + + public CDSOptions setArchiveName(String name) { + this.archiveName = name; + return this; + } + + + public CDSOptions setUseVersion(boolean use) { + this.useVersion = use; + return this; + } + + public CDSOptions setUseSystemArchive(boolean use) { + this.useSystemArchive = use; + return this; + } + + public CDSOptions setClassList(String[] list) { + this.classList = list; + return this; + } + public CDSOptions setClassList(ArrayList list) { + String array[] = new String[list.size()]; + list.toArray(array); + this.classList = array; + return this; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cds/CDSTestUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cds/CDSTestUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,593 @@ +/* + * 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. + */ +package jdk.test.lib.cds; + +import java.io.IOException; +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; + +// This class contains common test utilities for testing CDS +public class CDSTestUtils { + public static final String MSG_RANGE_NOT_WITHIN_HEAP = + "UseSharedSpaces: Unable to allocate region, range is not within java heap."; + public static final String MSG_RANGE_ALREADT_IN_USE = + "Unable to allocate region, java heap range is already in use."; + public static final String MSG_COMPRESSION_MUST_BE_USED = + "Unable to use shared archive: UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces."; + + public interface Checker { + public void check(OutputAnalyzer output) throws Exception; + } + + /* + * INTRODUCTION + * + * When testing various CDS functionalities, we need to launch JVM processes + * using a "launch method" (such as TestCommon.run), and analyze the results of these + * processes. + * + * While typical jtreg tests would use OutputAnalyzer in such cases, due to the + * complexity of CDS failure modes, we have added the CDSTestUtils.Result class + * to make the analysis more convenient and less error prone. + * + * A Java process can end in one of the following 4 states: + * + * 1: Unexpected error - such as JVM crashing. In this case, the "launch method" + * will throw a RuntimeException. + * 2: Mapping Failure - this happens when the OS (intermittently) fails to map the + * CDS archive, normally caused by Address Space Layout Randomization. + * We usually treat this as "pass". + * 3: Normal Exit - the JVM process has finished without crashing, and the exit code is 0. + * 4: Abnormal Exit - the JVM process has finished without crashing, and the exit code is not 0. + * + * In most test cases, we need to check the JVM process's output in cases 3 and 4. However, we need + * to make sure that our test code is not confused by case 2. + * + * For example, a JVM process is expected to print the string "Hi" and exit with 0. With the old + * CDSTestUtils.runWithArchive API, the test may be written as this: + * + * OutputAnalyzer out = CDSTestUtils.runWithArchive(args); + * out.shouldContain("Hi"); + * + * However, if the JVM process fails with mapping failure, the string "Hi" will not be in the output, + * and your test case will fail intermittently. + * + * Instead, the test case should be written as + * + * CDSTestUtils.run(args).assertNormalExit("Hi"); + * + * EXAMPLES/HOWTO + * + * 1. For simple substring matching: + * + * CDSTestUtils.run(args).assertNormalExit("Hi"); + * CDSTestUtils.run(args).assertNormalExit("a", "b", "x"); + * CDSTestUtils.run(args).assertAbnormalExit("failure 1", "failure2"); + * + * 2. For more complex output matching: using Lambda expressions + * + * CDSTestUtils.run(args) + * .assertNormalExit(output -> output.shouldNotContain("this should not be printed"); + * CDSTestUtils.run(args) + * .assertAbnormalExit(output -> { + * output.shouldNotContain("this should not be printed"); + * output.shouldHaveExitValue(123); + * }); + * + * 3. Chaining several checks: + * + * CDSTestUtils.run(args) + * .assertNormalExit(output -> output.shouldNotContain("this should not be printed") + * .assertNormalExit("should have this", "should have that"); + * + * 4. [Rare use case] if a test sometimes exit normally, and sometimes abnormally: + * + * CDSTestUtils.run(args) + * .ifNormalExit("ths string is printed when exiting with 0") + * .ifAbNormalExit("ths string is printed when exiting with 1"); + * + * NOTE: you usually don't want to write your test case like this -- it should always + * exit with the same exit code. (But I kept this API because some existing test cases + * behave this way -- need to revisit). + */ + public static class Result { + private final OutputAnalyzer output; + private final CDSOptions options; + private final boolean hasNormalExit; + private final String CDS_DISABLED = "warning: CDS is disabled when the"; + + public Result(CDSOptions opts, OutputAnalyzer out) throws Exception { + checkMappingFailure(out); + this.options = opts; + this.output = out; + hasNormalExit = (output.getExitValue() == 0); + + if (hasNormalExit) { + if ("on".equals(options.xShareMode) && + output.getStderr().contains("java version") && + !output.getStderr().contains(CDS_DISABLED)) { + // "-showversion" is always passed in the command-line by the execXXX methods. + // During normal exit, we require that the VM to show that sharing was enabled. + output.shouldContain("sharing"); + } + } + } + + public Result assertNormalExit(Checker checker) throws Exception { + checker.check(output); + output.shouldHaveExitValue(0); + return this; + } + + public Result assertAbnormalExit(Checker checker) throws Exception { + checker.check(output); + output.shouldNotHaveExitValue(0); + return this; + } + + // When {--limit-modules, --patch-module, and/or --upgrade-module-path} + // are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on. + public Result assertSilentlyDisabledCDS(Checker checker) throws Exception { + // this comes from a JVM warning message. + output.shouldContain(CDS_DISABLED); + checker.check(output); + return this; + } + + public Result assertSilentlyDisabledCDS(int exitCode, String... matches) throws Exception { + return assertSilentlyDisabledCDS((out) -> { + out.shouldHaveExitValue(exitCode); + checkMatches(out, matches); + }); + } + + public Result ifNormalExit(Checker checker) throws Exception { + if (hasNormalExit) { + checker.check(output); + } + return this; + } + + public Result ifAbnormalExit(Checker checker) throws Exception { + if (!hasNormalExit) { + checker.check(output); + } + return this; + } + + public Result ifNoMappingFailure(Checker checker) throws Exception { + checker.check(output); + return this; + } + + + public Result assertNormalExit(String... matches) throws Exception { + checkMatches(output, matches); + output.shouldHaveExitValue(0); + return this; + } + + public Result assertAbnormalExit(String... matches) throws Exception { + checkMatches(output, matches); + output.shouldNotHaveExitValue(0); + return this; + } + } + + // A number to be included in the filename of the stdout and the stderr output file. + static int logCounter = 0; + + private static int getNextLogCounter() { + return logCounter++; + } + + // By default, stdout of child processes are logged in files such as + // -0000-exec.stdout. If you want to also include the stdout + // inside jtr files, you can override this in the jtreg command line like + // "jtreg -Dtest.cds.copy.child.stdout=true ...." + public static final boolean copyChildStdoutToMainStdout = + Boolean.getBoolean("test.cds.copy.child.stdout"); + + // This property is passed to child test processes + public static final String TestTimeoutFactor = System.getProperty("test.timeout.factor", "1.0"); + + public static final String UnableToMapMsg = + "Unable to map shared archive: test did not complete"; + + // Create bootstrap CDS archive, + // use extra JVM command line args as a prefix. + // For CDS tests specifying prefix makes more sense than specifying suffix, since + // normally there are no classes or arguments to classes, just "-version" + // To specify suffix explicitly use CDSOptions.addSuffix() + public static OutputAnalyzer createArchive(String... cliPrefix) + throws Exception { + return createArchive((new CDSOptions()).addPrefix(cliPrefix)); + } + + // Create bootstrap CDS archive + public static OutputAnalyzer createArchive(CDSOptions opts) + throws Exception { + + startNewArchiveName(); + + ArrayList cmd = new ArrayList(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:dump"); + cmd.add("-Xlog:cds,cds+hashtables"); + if (opts.archiveName == null) + opts.archiveName = getDefaultArchiveName(); + cmd.add("-XX:SharedArchiveFile=./" + opts.archiveName); + + if (opts.classList != null) { + File classListFile = makeClassList(opts.classList); + cmd.add("-XX:ExtraSharedClassListFile=" + classListFile.getPath()); + } + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "dump"); + } + + + // check result of 'dump-the-archive' operation, that is "-Xshare:dump" + public static OutputAnalyzer checkDump(OutputAnalyzer output, String... extraMatches) + throws Exception { + + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + for (String match : extraMatches) { + output.shouldContain(match); + } + + return output; + } + + + // A commonly used convenience methods to create an archive and check the results + // Creates an archive and checks for errors + public static OutputAnalyzer createArchiveAndCheck(CDSOptions opts) + throws Exception { + return checkDump(createArchive(opts)); + } + + + public static OutputAnalyzer createArchiveAndCheck(String... cliPrefix) + throws Exception { + return checkDump(createArchive(cliPrefix)); + } + + + // This method should be used to check the output of child VM for common exceptions. + // Most of CDS tests deal with child VM processes for creating and using the archive. + // However exceptions that occur in the child process do not automatically propagate + // to the parent process. This mechanism aims to improve the propagation + // of exceptions and common errors. + // Exception e argument - an exception to be re-thrown if none of the common + // exceptions match. Pass null if you wish not to re-throw any exception. + public static void checkCommonExecExceptions(OutputAnalyzer output, Exception e) + throws Exception { + if (output.getStdout().contains("http://bugreport.java.com/bugreport/crash.jsp")) { + throw new RuntimeException("Hotspot crashed"); + } + if (output.getStdout().contains("TEST FAILED")) { + throw new RuntimeException("Test Failed"); + } + if (output.getOutput().contains("Unable to unmap shared space")) { + throw new RuntimeException("Unable to unmap shared space"); + } + + // Special case -- sometimes Xshare:on fails because it failed to map + // at given address. This behavior is platform-specific, machine config-specific + // and can be random (see ASLR). + if (isUnableToMap(output)) { + throw new SkippedException(UnableToMapMsg); + } + + if (e != null) { + throw e; + } + } + + public static void checkCommonExecExceptions(OutputAnalyzer output) throws Exception { + checkCommonExecExceptions(output, null); + } + + + // Check the output for indication that mapping of the archive failed. + // Performance note: this check seems to be rather costly - searching the entire + // output stream of a child process for multiple strings. However, it is necessary + // to detect this condition, a failure to map an archive, since this is not a real + // failure of the test or VM operation, and results in a test being "skipped". + // Suggestions to improve: + // 1. VM can designate a special exit code for such condition. + // 2. VM can print a single distinct string indicating failure to map an archive, + // instead of utilizing multiple messages. + // These are suggestions to improve testibility of the VM. However, implementing them + // could also improve usability in the field. + public static boolean isUnableToMap(OutputAnalyzer output) { + String outStr = output.getOutput(); + if ((output.getExitValue() == 1) && ( + outStr.contains("Unable to reserve shared space at required address") || + outStr.contains("Unable to map ReadOnly shared space at required address") || + outStr.contains("Unable to map ReadWrite shared space at required address") || + outStr.contains("Unable to map MiscData shared space at required address") || + outStr.contains("Unable to map MiscCode shared space at required address") || + outStr.contains("Unable to map OptionalData shared space at required address") || + outStr.contains("Could not allocate metaspace at a compatible address") || + outStr.contains("UseSharedSpaces: Unable to allocate region, range is not within java heap") )) + { + return true; + } + + return false; + } + + public static void checkMappingFailure(OutputAnalyzer out) throws SkippedException { + if (isUnableToMap(out)) { + throw new SkippedException(UnableToMapMsg); + } + } + + public static Result run(String... cliPrefix) throws Exception { + CDSOptions opts = new CDSOptions(); + opts.setArchiveName(getDefaultArchiveName()); + opts.addPrefix(cliPrefix); + return new Result(opts, runWithArchive(opts)); + } + + public static Result run(CDSOptions opts) throws Exception { + return new Result(opts, runWithArchive(opts)); + } + + // Execute JVM with CDS archive, specify command line args suffix + public static OutputAnalyzer runWithArchive(String... cliPrefix) + throws Exception { + + return runWithArchive( (new CDSOptions()) + .setArchiveName(getDefaultArchiveName()) + .addPrefix(cliPrefix) ); + } + + + // Execute JVM with CDS archive, specify CDSOptions + public static OutputAnalyzer runWithArchive(CDSOptions opts) + throws Exception { + + ArrayList cmd = new ArrayList(); + + for (String p : opts.prefix) cmd.add(p); + + cmd.add("-Xshare:" + opts.xShareMode); + cmd.add("-Dtest.timeout.factor=" + TestTimeoutFactor); + + if (!opts.useSystemArchive) { + if (opts.archiveName == null) + opts.archiveName = getDefaultArchiveName(); + cmd.add("-XX:SharedArchiveFile=" + opts.archiveName); + } + + if (opts.useVersion) + cmd.add("-version"); + + for (String s : opts.suffix) cmd.add(s); + + String[] cmdLine = cmd.toArray(new String[cmd.size()]); + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine); + return executeAndLog(pb, "exec"); + } + + + // A commonly used convenience methods to create an archive and check the results + // Creates an archive and checks for errors + public static OutputAnalyzer runWithArchiveAndCheck(CDSOptions opts) throws Exception { + return checkExec(runWithArchive(opts)); + } + + + public static OutputAnalyzer runWithArchiveAndCheck(String... cliPrefix) throws Exception { + return checkExec(runWithArchive(cliPrefix)); + } + + + public static OutputAnalyzer checkExec(OutputAnalyzer output, + String... extraMatches) throws Exception { + CDSOptions opts = new CDSOptions(); + return checkExec(output, opts, extraMatches); + } + + + // check result of 'exec' operation, that is when JVM is run using the archive + public static OutputAnalyzer checkExec(OutputAnalyzer output, CDSOptions opts, + String... extraMatches) throws Exception { + try { + if ("on".equals(opts.xShareMode)) { + output.shouldContain("sharing"); + } + output.shouldHaveExitValue(0); + } catch (RuntimeException e) { + checkCommonExecExceptions(output, e); + return output; + } + + checkMatches(output, extraMatches); + return output; + } + + + public static OutputAnalyzer checkExecExpectError(OutputAnalyzer output, + int expectedExitValue, + String... extraMatches) throws Exception { + if (isUnableToMap(output)) { + throw new SkippedException(UnableToMapMsg); + } + + output.shouldHaveExitValue(expectedExitValue); + checkMatches(output, extraMatches); + return output; + } + + public static OutputAnalyzer checkMatches(OutputAnalyzer output, + String... matches) throws Exception { + for (String match : matches) { + output.shouldContain(match); + } + return output; + } + + + // get the file object for the test artifact + public static File getTestArtifact(String name, boolean checkExistence) { + File dir = new File(System.getProperty("test.classes", ".")); + File file = new File(dir, name); + + if (checkExistence && !file.exists()) { + throw new RuntimeException("Cannot find " + file.getPath()); + } + + return file; + } + + + // create file containing the specified class list + public static File makeClassList(String classes[]) + throws Exception { + return makeClassList(getTestName() + "-", classes); + } + + // create file containing the specified class list + public static File makeClassList(String testCaseName, String classes[]) + throws Exception { + + File classList = getTestArtifact(testCaseName + "test.classlist", false); + FileOutputStream fos = new FileOutputStream(classList); + PrintStream ps = new PrintStream(fos); + + addToClassList(ps, classes); + + ps.close(); + fos.close(); + + return classList; + } + + + public static void addToClassList(PrintStream ps, String classes[]) + throws IOException + { + if (classes != null) { + for (String s : classes) { + ps.println(s); + } + } + } + + + // Optimization for getting a test name. + // Test name does not change during execution of the test, + // but getTestName() uses stack walking hence it is expensive. + // Therefore cache it and reuse it. + private static String testName; + public static String getTestName() { + if (testName == null) { + testName = Utils.getTestName(); + } + return testName; + } + + private static final SimpleDateFormat timeStampFormat = + new SimpleDateFormat("HH'h'mm'm'ss's'SSS"); + + private static String defaultArchiveName; + + // Call this method to start new archive with new unique name + public static void startNewArchiveName() { + defaultArchiveName = getTestName() + + timeStampFormat.format(new Date()) + ".jsa"; + } + + public static String getDefaultArchiveName() { + return defaultArchiveName; + } + + + // ===================== FILE ACCESS convenience methods + public static File getOutputFile(String name) { + File dir = new File(System.getProperty("test.classes", ".")); + return new File(dir, getTestName() + "-" + name); + } + + + public static File getOutputSourceFile(String name) { + File dir = new File(System.getProperty("test.classes", ".")); + return new File(dir, name); + } + + + public static File getSourceFile(String name) { + File dir = new File(System.getProperty("test.src", ".")); + return new File(dir, name); + } + + + // ============================= Logging + public static OutputAnalyzer executeAndLog(ProcessBuilder pb, String logName) throws Exception { + long started = System.currentTimeMillis(); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + String outputFileNamePrefix = + getTestName() + "-" + String.format("%04d", getNextLogCounter()) + "-" + logName; + + writeFile(getOutputFile(outputFileNamePrefix + ".stdout"), output.getStdout()); + writeFile(getOutputFile(outputFileNamePrefix + ".stderr"), output.getStderr()); + System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]"); + System.out.println("[logging stdout to " + outputFileNamePrefix + ".stdout]"); + System.out.println("[logging stderr to " + outputFileNamePrefix + ".stderr]"); + System.out.println("[STDERR]\n" + output.getStderr()); + + if (copyChildStdoutToMainStdout) + System.out.println("[STDOUT]\n" + output.getStdout()); + + return output; + } + + + private static void writeFile(File file, String content) throws Exception { + FileOutputStream fos = new FileOutputStream(file); + PrintStream ps = new PrintStream(fos); + ps.print(content); + ps.close(); + fos.close(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/classloader/ClassLoadUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/classloader/ClassLoadUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.classloader; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.FileInputStream; + +public class ClassLoadUtils { + + private ClassLoadUtils() { + } + + /** + * Get filename of class file from classpath for given class name. + * + * @param className class name + * @return filename or null if not found + */ + public static String getClassPath(String className) { + String fileName = className.replace(".", File.separator) + ".class"; + String[] classPath = System.getProperty("java.class.path").split(File.pathSeparator); + File target = null; + int i; + for (i = 0; i < classPath.length; ++i) { + target = new File(classPath[i] + File.separator + fileName); + System.out.println("Try: " + target); + if (target.exists()) { + break; + } + } + if (i != classPath.length) { + return classPath[i]; + } + return null; + } + + /** + * Get filename of class file from classpath for given class name. + * + * @param className class name + * @return filename or null if not found + */ + public static String getClassPathFileName(String className) { + String fileName = className.replace(".", File.separator) + ".class"; + String[] classPath = System.getProperty("java.class.path").split(File.pathSeparator); + File target = null; + int i; + for (i = 0; i < classPath.length; ++i) { + target = new File(classPath[i] + File.separator + fileName); + System.out.println("Try: " + target); + if (target.exists()) { + break; + } + } + if (i != classPath.length) { + try { + return target.getCanonicalPath(); + } catch (IOException e) { + return null; + } + } + return null; + } + + public static String getRedefineClassFileName(String dir, String className) { + String fileName = getClassPathFileName(className); + if (fileName == null) { + return null; + } + if (fileName.contains("classes")) { + return fileName.replace("classes", dir); + } else { + String classPath = getClassPath(className); + if (classPath != null) { + return classPath + File.separator + "newclass" + File.separator + className.replace(".", File.separator) + ".class"; + } else { + return null; + } + } + } + + /** + * Get filename of class file which is to be redefined. + */ + public static String getRedefineClassFileName(String className) { + return getRedefineClassFileName("newclass", className); + } + + /** + * 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)); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/classloader/FilterClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/classloader/FilterClassLoader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.classloader; + +import java.util.function.Predicate; +/** + * A classloader, which using target classloader in case provided condition + * for class name is met, and using parent otherwise + */ +public class FilterClassLoader extends ClassLoader { + + private final ClassLoader target; + private final Predicate condition; + + public FilterClassLoader(ClassLoader target, ClassLoader parent, + Predicate condition) { + super(parent); + this.condition = condition; + this.target = target; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (condition.test(name)) { + return target.loadClass(name); + } + return super.loadClass(name); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/classloader/GeneratingClassLoader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.classloader; + +import java.io.*; +import java.util.*; + +/** + * Classloader that generates classes on the fly. + * + * This classloader can load classes with name starting with 'Class'. It will + * use 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 Metaspace. + */ +class TemplateClass { +} + +public class GeneratingClassLoader extends ClassLoader { + + 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; + } + + /** + * 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 RuntimeException(e); + } + } + + /** + * Create generating class loader that will use class file for + * nsk.share.classload.TemplateClass as template. + */ + public GeneratingClassLoader() { + this(TemplateClass.class.getName()); + } + + public int getNameLength() { + return templateClassName.length(); + } + + 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(); + } + + 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 RuntimeException(e); + } + } + + private byte[] getByteCode() throws ClassNotFoundException { + if (bytecode == null) { + readByteCode(); + } + if (offsets == null) { + getOffsets(bytecode); + if (offsets == null) { + throw new RuntimeException("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 = ClassLoadUtils.readFile(target); + } catch (IOException e) { + throw new ClassNotFoundException(templateClassName, e); + } + } + + private void getOffsets(byte[] bytecode) { + List offsets = new ArrayList(); + 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 RuntimeException(e); + } + this.offsets = new int[offsets.size()]; + for (int i = 0; i < offsets.size(); ++i) { + this.offsets[i] = offsets.get(i).intValue(); + } + } + } + + public static final String DEFAULT_CLASSNAME = TemplateClass.class.getName(); + 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; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/classloader/ParentLastURLClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/classloader/ParentLastURLClassLoader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.classloader; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * An url classloader, which trying to load class from provided URL[] first, + * and using parent classloader in case it failed + */ +public class ParentLastURLClassLoader extends URLClassLoader { + + public ParentLastURLClassLoader(URL urls[], ClassLoader parent) { + super(urls, parent); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + try { + Class c = findClass(name); + if (c != null) { + return c; + } + } catch (ClassNotFoundException e) { + // ignore + } + return super.loadClass(name); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/CPUSpecificCommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/CPUSpecificCommandLineOptionTest.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli; + +import jdk.test.lib.cli.predicate.CPUSpecificPredicate; + +/** + * Base class for command line options tests that + * requires specific CPU arch or specific CPU features. + */ +public abstract class CPUSpecificCommandLineOptionTest + extends CommandLineOptionTest { + /** + * Creates new CPU specific test instance that does not + * require any CPU features. + * + * @param cpuArchPattern Regular expression that should + * match os.arch. + */ + public CPUSpecificCommandLineOptionTest(String cpuArchPattern) { + this(cpuArchPattern, null, null); + } + + /** + * Creates new CPU specific test instance that does not + * require from CPU support of {@code supportedCPUFeatures} features + * and no support of {@code unsupportedCPUFeatures}. + * + * @param cpuArchPattern Regular expression that should + * match os.arch. + * @param supportedCPUFeatures Array with names of features that + * should be supported by CPU. If {@code null}, + * then no features have to be supported. + * @param unsupportedCPUFeatures Array with names of features that + * should not be supported by CPU. + * If {@code null}, then CPU may support any + * features. + */ + public CPUSpecificCommandLineOptionTest(String cpuArchPattern, + String supportedCPUFeatures[], String unsupportedCPUFeatures[]) { + super(new CPUSpecificPredicate(cpuArchPattern, supportedCPUFeatures, + unsupportedCPUFeatures)); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/CommandLineOptionTest.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli; + +import java.util.List; +import java.util.ArrayList; +import java.util.Collections; +import java.util.function.BooleanSupplier; + +import jdk.test.lib.management.InputArguments; +import jdk.test.lib.process.ExitCode; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.Utils; + +/** + * Base class for command line option tests. + */ +public abstract class CommandLineOptionTest { + public static final String UNLOCK_DIAGNOSTIC_VM_OPTIONS + = "-XX:+UnlockDiagnosticVMOptions"; + public static final String UNLOCK_EXPERIMENTAL_VM_OPTIONS + = "-XX:+UnlockExperimentalVMOptions"; + protected static final String UNRECOGNIZED_OPTION_ERROR_FORMAT + = "Unrecognized VM option '[+-]?%s(=.*)?'"; + protected static final String EXPERIMENTAL_OPTION_ERROR_FORMAT + = "VM option '%s' is experimental and must be enabled via " + + "-XX:\\+UnlockExperimentalVMOptions."; + protected static final String DIAGNOSTIC_OPTION_ERROR_FORMAT + = " VM option '%s' is diagnostic and must be enabled via " + + "-XX:\\+UnlockDiagnosticVMOptions."; + private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s"; + + /** + * Verifies that JVM startup behavior matches our expectations. + * + * @param option an option that should be passed to JVM + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitErrorMessage message that will be shown if exit code is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. + * @param exitCode expected exit code. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyJVMStartup(String option, + String expectedMessages[], String unexpectedMessages[], + String exitErrorMessage, String wrongWarningMessage, + ExitCode exitCode) throws Throwable { + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitErrorMessage, + wrongWarningMessage, exitCode, false, option); + } + + /** + * Verifies that JVM startup behavior matches our expectations. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitErrorMessage message that will be shown if exit code is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. + * @param exitCode expected exit code. + * @param addTestVMOptions if {@code true} then test VM options will be + * passed to VM. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyJVMStartup(String expectedMessages[], + String unexpectedMessages[], String exitErrorMessage, + String wrongWarningMessage, ExitCode exitCode, + boolean addTestVMOptions, String... options) + throws Throwable { + List finalOptions = new ArrayList<>(); + if (addTestVMOptions) { + Collections.addAll(finalOptions, InputArguments.getVmInputArgs()); + Collections.addAll(finalOptions, Utils.getTestJavaOpts()); + } + Collections.addAll(finalOptions, options); + finalOptions.add("-version"); + + ProcessBuilder processBuilder + = ProcessTools.createJavaProcessBuilder(finalOptions.toArray( + new String[finalOptions.size()])); + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); + + try { + outputAnalyzer.shouldHaveExitValue(exitCode.value); + } catch (RuntimeException e) { + String errorMessage = String.format( + "JVM process should have exit value '%d'.%n%s", + exitCode.value, exitErrorMessage); + throw new AssertionError(errorMessage, e); + } + + verifyOutput(expectedMessages, unexpectedMessages, + wrongWarningMessage, outputAnalyzer); + } + + /** + * Verifies that JVM startup behavior matches our expectations. + * + * @param expectedMessages an array of patterns that should occur in JVM + * output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param wrongWarningMessage message that will be shown if messages are + * not as expected. + * @param outputAnalyzer OutputAnalyzer instance + * @throws AssertionError if verification fails. + */ + public static void verifyOutput(String[] expectedMessages, + String[] unexpectedMessages, String wrongWarningMessage, + OutputAnalyzer outputAnalyzer) { + if (expectedMessages != null) { + for (String expectedMessage : expectedMessages) { + try { + outputAnalyzer.shouldMatch(expectedMessage); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Expected message not found: '%s'.%n%s", + expectedMessage, wrongWarningMessage); + throw new AssertionError(errorMessage, e); + } + } + } + + if (unexpectedMessages != null) { + for (String unexpectedMessage : unexpectedMessages) { + try { + outputAnalyzer.shouldNotMatch(unexpectedMessage); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Unexpected message found: '%s'.%n%s", + unexpectedMessage, wrongWarningMessage); + throw new AssertionError(errorMessage, e); + } + } + } + } + + /** + * Verifies that JVM startup behavior matches our expectations when type + * of newly started VM is the same as the type of current. + * + * @param expectedMessages an array of patterns that should occur + * in JVM output. If {@code null} then + * JVM output could be empty. + * @param unexpectedMessages an array of patterns that should not + * occur in JVM output. If {@code null} then + * JVM output could be empty. + * @param exitErrorMessage Message that will be shown if exit value is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. + * @param exitCode expected exit code. + * @param options options that should be passed to VM in addition to mode + * flag. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifySameJVMStartup(String expectedMessages[], + String unexpectedMessages[], String exitErrorMessage, + String wrongWarningMessage, ExitCode exitCode, String... options) + throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + String extraFlagForEmulated = CommandLineOptionTest.getVMTypeOptionForEmulated(); + if (extraFlagForEmulated != null) { + finalOptions.add(extraFlagForEmulated); + } + Collections.addAll(finalOptions, options); + + CommandLineOptionTest.verifyJVMStartup(expectedMessages, + unexpectedMessages, exitErrorMessage, + wrongWarningMessage, exitCode, false, + finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Verifies that value of specified JVM option is the same as + * expected value. + * This method filter out option with {@code optionName} + * name from test java options. + * + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param optionErrorString message will be shown if option value is not as + * expected. + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValue(String optionName, + String expectedValue, String optionErrorString, + String... additionalVMOpts) throws Throwable { + verifyOptionValue(optionName, expectedValue, optionErrorString, + true, additionalVMOpts); + } + + /** + * Verifies that value of specified JVM option is the same as + * expected value. + * This method filter out option with {@code optionName} + * name from test java options. + * + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param addTestVmOptions if {@code true}, then test VM options + * will be used. + * @param optionErrorString message will be shown if option value is not as + * expected. + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues + * occur. + */ + public static void verifyOptionValue(String optionName, + String expectedValue, String optionErrorString, + boolean addTestVmOptions, String... additionalVMOpts) + throws Throwable { + List vmOpts = new ArrayList<>(); + + if (addTestVmOptions) { + Collections.addAll(vmOpts, + Utils.getFilteredTestJavaOpts(optionName)); + } + Collections.addAll(vmOpts, additionalVMOpts); + Collections.addAll(vmOpts, "-XX:+PrintFlagsFinal", "-version"); + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); + + OutputAnalyzer outputAnalyzer + = new OutputAnalyzer(processBuilder.start()); + + try { + outputAnalyzer.shouldHaveExitValue(0); + } catch (RuntimeException e) { + String errorMessage = String.format( + "JVM should start with option '%s' without errors.", + optionName); + throw new AssertionError(errorMessage, e); + } + verifyOptionValue(optionName, expectedValue, optionErrorString, + outputAnalyzer); + } + + /** + * Verifies that value of specified JVM option is the same as + * expected value. + * + * @param optionName a name of tested option. + * @param expectedValue expected value of tested option. + * @param optionErrorString message will be shown if option value is not + * as expected. + * @param outputAnalyzer OutputAnalyzer instance + * @throws AssertionError if verification fails + */ + public static void verifyOptionValue(String optionName, + String expectedValue, String optionErrorString, + OutputAnalyzer outputAnalyzer) { + try { + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionName, expectedValue)); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Option '%s' is expected to have '%s' value%n%s", + optionName, expectedValue, + optionErrorString); + throw new AssertionError(errorMessage, e); + } + } + + /** + * Start VM with given options and values. + * Generates command line option flags from + * {@code optionNames} and {@code optionValues}. + * + * @param optionNames names of options to pass in + * @param optionValues values of option + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @return output from vm process + */ + public static OutputAnalyzer startVMWithOptions(String[] optionNames, + String[] optionValues, + String... additionalVMOpts) throws Throwable { + List vmOpts = new ArrayList<>(); + if (optionNames == null || optionValues == null || optionNames.length != optionValues.length) { + throw new IllegalArgumentException("optionNames and/or optionValues"); + } + + for (int i = 0; i < optionNames.length; i++) { + vmOpts.add(prepareFlag(optionNames[i], optionValues[i])); + } + Collections.addAll(vmOpts, additionalVMOpts); + Collections.addAll(vmOpts, "-version"); + + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder( + vmOpts.toArray(new String[vmOpts.size()])); + + return new OutputAnalyzer(processBuilder.start()); + } + + /** + * Verifies from the output that values of specified JVM options were the same as + * expected values. + * + * @param outputAnalyzer search output for expect options and values. + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValuesFromOutput(OutputAnalyzer outputAnalyzer, + String[] optionNames, + String[] expectedValues) throws Throwable { + outputAnalyzer.shouldHaveExitValue(0); + for (int i = 0; i < optionNames.length; i++) { + outputAnalyzer.shouldMatch(String.format( + CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, + optionNames[i], expectedValues[i])); + } + } + + /** + * Verifies that value of specified JVM options are the same as + * expected values. + * Generates command line option flags from + * {@code optionNames} and {@code expectedValues}. + * + * @param optionNames names of tested options. + * @param expectedValues expected values of tested options. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValues(String[] optionNames, + String[] expectedValues) throws Throwable { + OutputAnalyzer outputAnalyzer = startVMWithOptions(optionNames, expectedValues, "-XX:+PrintFlagsFinal"); + verifyOptionValuesFromOutput(outputAnalyzer, optionNames, expectedValues); + } + + /** + * Verifies that value of specified JVM when type of newly started VM + * is the same as the type of current. + * This method filter out option with {@code optionName} + * name from test java options. + * Only mode flag will be passed to VM in addition to + * {@code additionalVMOpts} + * + * @param optionName name of tested option. + * @param expectedValue expected value of tested option. + * @param optionErrorString message to show if option has another value + * @param additionalVMOpts additional options that should be + * passed to JVM. + * @throws Throwable if verification fails or some other issues occur. + */ + public static void verifyOptionValueForSameVM(String optionName, + String expectedValue, String optionErrorString, + String... additionalVMOpts) throws Throwable { + List finalOptions = new ArrayList<>(); + finalOptions.add(CommandLineOptionTest.getVMTypeOption()); + String extraFlagForEmulated = CommandLineOptionTest.getVMTypeOptionForEmulated(); + if (extraFlagForEmulated != null) { + finalOptions.add(extraFlagForEmulated); + } + Collections.addAll(finalOptions, additionalVMOpts); + + CommandLineOptionTest.verifyOptionValue(optionName, expectedValue, + optionErrorString, false, + finalOptions.toArray(new String[finalOptions.size()])); + } + + /** + * Prepares boolean command line flag with name {@code name} according + * to it's {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareBooleanFlag(String name, boolean value) { + return String.format("-XX:%c%s", (value ? '+' : '-'), name); + } + + /** + * Prepares numeric command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option + * @return prepared command line flag + */ + public static String prepareNumericFlag(String name, Number value) { + return String.format("-XX:%s=%s", name, value.toString()); + } + + /** + * Prepares generic command line flag with name {@code name} by setting + * it's value to {@code value}. + * + * @param name the name of option to be prepared + * @param value the value of option ("+" or "-" can be used instead of "true" or "false") + * @return prepared command line flag + */ + public static String prepareFlag(String name, String value) { + if (value.equals("+") || value.equalsIgnoreCase("true")) { + return "-XX:+" + name; + } else if (value.equals("-") || value.equalsIgnoreCase("false")) { + return "-XX:-" + name; + } else { + return "-XX:" + name + "=" + value; + } + } + + /** + * Returns message that should occur in VM output if option + * {@code optionName} if unrecognized. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is unrecognized + */ + public static String getUnrecognizedOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.UNRECOGNIZED_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * Returns message that should occur in VM output if option + * {@code optionName} is experimental and + * -XX:+UnlockExperimentalVMOptions was not passed to VM. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is experimental + */ + public static String getExperimentalOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.EXPERIMENTAL_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * Returns message that should occur in VM output if option + * {@code optionName} is diagnostic and -XX:+UnlockDiagnosticVMOptions + * was not passed to VM. + * + * @param optionName the name of option for which message should be returned + * @return message saying that option {@code optionName} is diganostic + */ + public static String getDiagnosticOptionErrorMessage(String optionName) { + return String.format( + CommandLineOptionTest.DIAGNOSTIC_OPTION_ERROR_FORMAT, + optionName); + } + + /** + * @return option required to start a new VM with the same type as current. + * @throws RuntimeException when VM type is unknown. + */ + private static String getVMTypeOption() { + if (Platform.isServer()) { + return "-server"; + } else if (Platform.isClient()) { + return "-client"; + } else if (Platform.isMinimal()) { + return "-minimal"; + } else if (Platform.isGraal()) { + return "-graal"; + } + throw new RuntimeException("Unknown VM mode."); + } + + /** + * @return addtional VMoptions(Emulated related) required to start a new VM with the same type as current. + */ + private static String getVMTypeOptionForEmulated() { + if (Platform.isServer() && !Platform.isEmulatedClient()) { + return "-XX:-NeverActAsServerClassMachine"; + } else if (Platform.isEmulatedClient()) { + return "-XX:+NeverActAsServerClassMachine"; + } + return null; + } + + private final BooleanSupplier predicate; + + /** + * Constructs new CommandLineOptionTest that will be executed only if + * predicate {@code predicate} return {@code true}. + * @param predicate a predicate responsible for test's preconditions check. + */ + public CommandLineOptionTest(BooleanSupplier predicate) { + this.predicate = predicate; + } + + /** + * Runs command line option test. + */ + public final void test() throws Throwable { + if (predicate.getAsBoolean()) { + runTestCases(); + } + } + + /** + * @throws Throwable if some issue happened during test cases execution. + */ + protected abstract void runTestCases() throws Throwable; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/predicate/AndPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/predicate/AndPredicate.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class AndPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + private final BooleanSupplier c; + + public AndPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + this.c = () -> true; // Boolean.TRUE::booleanValue + } + + public AndPredicate(BooleanSupplier a, BooleanSupplier b, BooleanSupplier c) { + this.a = a; + this.b = b; + this.c = c; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() && b.getAsBoolean() && c.getAsBoolean(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/predicate/CPUSpecificPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/predicate/CPUSpecificPredicate.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli.predicate; + +import jdk.test.lib.Platform; +import sun.hotspot.cpuinfo.CPUInfo; + +import java.util.function.BooleanSupplier; + +public class CPUSpecificPredicate implements BooleanSupplier { + private final String cpuArchPattern; + private final String supportedCPUFeatures[]; + private final String unsupportedCPUFeatures[]; + + public CPUSpecificPredicate(String cpuArchPattern, + String supportedCPUFeatures[], + String unsupportedCPUFeatures[]) { + this.cpuArchPattern = cpuArchPattern; + this.supportedCPUFeatures = supportedCPUFeatures; + this.unsupportedCPUFeatures = unsupportedCPUFeatures; + } + + @Override + public boolean getAsBoolean() { + if (!Platform.getOsArch().matches(cpuArchPattern)) { + System.out.println("CPU arch " + Platform.getOsArch() + " does not match " + cpuArchPattern); + return false; + } + + if (supportedCPUFeatures != null) { + for (String feature : supportedCPUFeatures) { + if (!CPUInfo.hasFeature(feature)) { + System.out.println("CPU does not support " + feature + + " feature"); + return false; + } + } + } + + if (unsupportedCPUFeatures != null) { + for (String feature : unsupportedCPUFeatures) { + if (CPUInfo.hasFeature(feature)) { + System.out.println("CPU support " + feature + " feature"); + return false; + } + } + } + return true; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/predicate/NotPredicate.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class NotPredicate implements BooleanSupplier { + private final BooleanSupplier s; + + public NotPredicate(BooleanSupplier s) { + this.s = s; + } + + @Override + public boolean getAsBoolean() { + return !s.getAsBoolean(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/cli/predicate/OrPredicate.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.cli.predicate; + +import java.util.function.BooleanSupplier; + +public class OrPredicate implements BooleanSupplier { + private final BooleanSupplier a; + private final BooleanSupplier b; + + public OrPredicate(BooleanSupplier a, BooleanSupplier b) { + this.a = a; + this.b = b; + } + + @Override + public boolean getAsBoolean() { + return a.getAsBoolean() || b.getAsBoolean(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/compiler/CompilerUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/compiler/CompilerUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.compiler; + +import javax.tools.JavaCompiler; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * This class consists exclusively of static utility methods for invoking the + * java compiler. + */ +public final class CompilerUtils { + private CompilerUtils() { } + + /** + * Compile all the java sources in {@code /**} to + * {@code /**}. The destination directory will be created if + * it doesn't exist. + * + * Equivalent to calling {@code compile(source, destination, true, options);}. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @param source Path to the source directory + * @param destination Path to the destination directory + * @param options Any options to pass to the compiler + * + * @return true if the compilation is successful + * + * @throws IOException + * if there is an I/O error scanning the source tree or + * creating the destination directory + * @throws UnsupportedOperationException + * if there is no system java compiler + */ + public static boolean compile(Path source, Path destination, String... options) + throws IOException + { + return compile(source, destination, true, options); + } + + /** + * Compile all the java sources in {@code } and optionally its + * subdirectories, to + * {@code }. The destination directory will be created if + * it doesn't exist. + * + * All warnings/errors emitted by the compiler are output to System.out/err. + * + * @param source Path to the source directory + * @param destination Path to the destination directory + * @param recurse If {@code true} recurse into any {@code source} subdirectories + * to compile all java source files; else only compile those directly in + * {@code source}. + * @param options Any options to pass to the compiler + * + * @return true if the compilation is successful + * + * @throws IOException + * if there is an I/O error scanning the source tree or + * creating the destination directory + * @throws UnsupportedOperationException + * if there is no system java compiler + */ + + public static boolean compile(Path source, Path destination, boolean recurse, String... options) + throws IOException + { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + // no compiler available + throw new UnsupportedOperationException("Unable to get system java compiler. " + + "Perhaps, jdk.compiler module is not available."); + } + StandardJavaFileManager jfm = compiler.getStandardFileManager(null, null, null); + + List sources + = Files.find(source, (recurse ? Integer.MAX_VALUE : 1), + (file, attrs) -> (file.toString().endsWith(".java"))) + .collect(Collectors.toList()); + + Files.createDirectories(destination); + jfm.setLocation(StandardLocation.CLASS_PATH, Collections.emptyList()); + jfm.setLocationFromPaths(StandardLocation.CLASS_OUTPUT, + Collections.singletonList(destination)); + + List opts = Arrays.asList(options); + JavaCompiler.CompilationTask task + = compiler.getTask(null, jfm, null, opts, null, + jfm.getJavaFileObjectsFromPaths(sources)); + + return task.call(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.compiler; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.tools.ForwardingJavaFileManager; +import javax.tools.FileObject; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +/** + * {@code InMemoryJavaCompiler} can be used for compiling a {@link + * CharSequence} to a {@code byte[]}. + * + * The compiler will not use the file system at all, instead using a {@link + * ByteArrayOutputStream} for storing the byte code. For the source code, any + * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link + * StringBuffer} or {@link StringBuilder}. + * + * The {@code InMemoryCompiler} can easily be used together with a {@code + * ByteClassLoader} to easily compile and load source code in a {@link String}: + * + *

+ * {@code
+ * import jdk.test.lib.compiler.InMemoryJavaCompiler;
+ * import jdk.test.lib.ByteClassLoader;
+ *
+ * class Example {
+ *     public static void main(String[] args) {
+ *         String className = "Foo";
+ *         String sourceCode = "public class " + className + " {" +
+ *                             "    public void bar() {" +
+ *                             "        System.out.println("Hello from bar!");" +
+ *                             "    }" +
+ *                             "}";
+ *         byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode);
+ *         Class fooClass = ByteClassLoader.load(className, byteCode);
+ *     }
+ * }
+ * }
+ * 
+ */ +public class InMemoryJavaCompiler { + private static class MemoryJavaFileObject extends SimpleJavaFileObject { + private final String className; + private final CharSequence sourceCode; + private final ByteArrayOutputStream byteCode; + + public MemoryJavaFileObject(String className, CharSequence sourceCode) { + super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE); + this.className = className; + this.sourceCode = sourceCode; + this.byteCode = new ByteArrayOutputStream(); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return sourceCode; + } + + @Override + public OutputStream openOutputStream() throws IOException { + return byteCode; + } + + public byte[] getByteCode() { + return byteCode.toByteArray(); + } + + public String getClassName() { + return className; + } + } + + private static class FileManagerWrapper extends ForwardingJavaFileManager { + private static final Location PATCH_LOCATION = new Location() { + @Override + public String getName() { + return "patch module location"; + } + + @Override + public boolean isOutputLocation() { + return false; + } + }; + private final MemoryJavaFileObject file; + private final String moduleOverride; + + public FileManagerWrapper(MemoryJavaFileObject file, String moduleOverride) { + super(getCompiler().getStandardFileManager(null, null, null)); + this.file = file; + this.moduleOverride = moduleOverride; + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, + Kind kind, FileObject sibling) + throws IOException { + if (!file.getClassName().equals(className)) { + throw new IOException("Expected class with name " + file.getClassName() + + ", but got " + className); + } + return file; + } + + @Override + public Location getLocationForModule(Location location, JavaFileObject fo) throws IOException { + if (fo == file && moduleOverride != null) { + return PATCH_LOCATION; + } + return super.getLocationForModule(location, fo); + } + + @Override + public String inferModuleName(Location location) throws IOException { + if (location == PATCH_LOCATION) { + return moduleOverride; + } + return super.inferModuleName(location); + } + + @Override + public boolean hasLocation(Location location) { + return super.hasLocation(location) || location == StandardLocation.PATCH_MODULE_PATH; + } + + } + + /** + * Compiles the class with the given name and source code. + * + * @param className The name of the class + * @param sourceCode The source code for the class with name {@code className} + * @param options additional command line options + * @throws RuntimeException if the compilation did not succeed + * @return The resulting byte code from the compilation + */ + public static byte[] compile(String className, CharSequence sourceCode, String... options) { + MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode); + CompilationTask task = getCompilationTask(file, options); + + if(!task.call()) { + throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode); + } + + return file.getByteCode(); + } + + private static JavaCompiler getCompiler() { + return ToolProvider.getSystemJavaCompiler(); + } + + private static CompilationTask getCompilationTask(MemoryJavaFileObject file, String... options) { + List opts = new ArrayList<>(); + String moduleOverride = null; + for (String opt : options) { + if (opt.startsWith("--patch-module=")) { + moduleOverride = opt.substring("--patch-module=".length()); + } else { + opts.add(opt); + } + } + return getCompiler().getTask(null, new FileManagerWrapper(file, moduleOverride), null, opts, null, Arrays.asList(file)); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/compiler/ModuleInfoMaker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/compiler/ModuleInfoMaker.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.compiler; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +/** + * Utility class for creating test modules. + */ +public class ModuleInfoMaker { + private static final String MODULE_INFO_JAVA = "module-info.java"; + private static final Pattern MODULE_PATTERN = + Pattern.compile("module\\s+((?:\\w+\\.)*)"); + private static final Pattern PACKAGE_PATTERN = + Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))"); + private static final Pattern CLASS_PATTERN = + Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)"); + + private final Path dir; + + public ModuleInfoMaker(Path dir) { + this.dir = dir; + } + + /** + * Create java source files of the given module + */ + public void writeJavaFiles(String module, String moduleInfoJava, String... contents) + throws IOException + { + Path msrc = dir.resolve(module); + new JavaSource(moduleInfoJava).write(msrc); + for (String c : contents) { + new JavaSource(c).write(msrc); + } + } + + /** + * Compile the module to the given destination. + */ + public void compile(String module, Path dest, String... options) + throws IOException + { + Path msrc = dir.resolve(module); + String[] args = + Stream.concat(Arrays.stream(options), + Stream.of("--module-source-path", + dir.toString())).toArray(String[]::new); + if (!CompilerUtils.compile(msrc, dest, args)) { + throw new Error("Fail to compile " + module); + } + } + + static class JavaSource { + final String source; + JavaSource(String source) { + this.source = source; + } + + /** + * Writes the source code to a file in a specified directory. + * @param dir the directory + * @throws IOException if there is a problem writing the file + */ + public void write(Path dir) throws IOException { + Path file = dir.resolve(getJavaFileNameFromSource(source)); + Files.createDirectories(file.getParent()); + try (BufferedWriter out = Files.newBufferedWriter(file)) { + out.write(source.replace("\n", System.lineSeparator())); + } + } + + /** + * Extracts the Java file name from the class declaration. + * This method is intended for simple files and uses regular expressions, + * so comments matching the pattern can make the method fail. + */ + static String getJavaFileNameFromSource(String source) { + String packageName = null; + + Matcher matcher = MODULE_PATTERN.matcher(source); + if (matcher.find()) + return MODULE_INFO_JAVA; + + matcher = PACKAGE_PATTERN.matcher(source); + if (matcher.find()) + packageName = matcher.group(1).replace(".", "/"); + + matcher = CLASS_PATTERN.matcher(source); + if (matcher.find()) { + String className = matcher.group(1) + ".java"; + return (packageName == null) ? className : packageName + "/" + className; + } else if (packageName != null) { + return packageName + "/package-info.java"; + } else { + throw new Error("Could not extract the java class " + + "name from the provided source"); + } + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/cgroup/CPUSetsReader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,155 @@ +/* + * 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. + */ + +package jdk.test.lib.containers.cgroup; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import jdk.test.lib.Asserts; + + +// A simple CPU sets reader and parser +public class CPUSetsReader { + public static String PROC_SELF_STATUS_PATH = "/proc/self/status"; + + // Test the parser + public static void test() { + assertParse("0-7", "0,1,2,3,4,5,6,7"); + assertParse("1,3,6", "1,3,6"); + assertParse("0,2-4,6,10-11", "0,2,3,4,6,10,11"); + assertParse("0", "0"); + } + + + private static void assertParse(String cpuSet, String expectedResult) { + Asserts.assertEquals(listToString(parseCpuSet(cpuSet)), expectedResult); + } + + public static int getNumCpus() { + String path = "/proc/cpuinfo"; + try { + Stream stream = Files.lines(Paths.get(path)); + return (int) stream.filter(line -> line.startsWith("processor")).count(); + } catch (IOException e) { + return 0; + } + } + + + public static String readFromProcStatus(String setType) { + String path = PROC_SELF_STATUS_PATH; + Optional o = Optional.empty(); + + System.out.println("readFromProcStatus() entering for: " + setType); + + try (Stream stream = Files.lines(Paths.get(path))) { + o = stream + .filter(line -> line.contains(setType)) + .findFirst(); + } catch (IOException e) { + return null; + } + + if (!o.isPresent()) { + return null; // entry not found + } + + String[] parts = o.get().replaceAll("\\s", "").split(":"); + + // Should be 2 parts, before and after ":" + Asserts.assertEquals(parts.length, 2); + + String result = parts[1]; + System.out.println("readFromProcStatus() returning: " + result); + return result; + } + + + public static List parseCpuSet(String value) { + ArrayList result = new ArrayList(); + + try { + String[] commaSeparated = value.split(","); + + for (String item : commaSeparated) { + if (item.contains("-")) { + addRange(result, item); + } else { + result.add(Integer.parseInt(item)); + } + } + } catch (Exception e) { + System.err.println("Exception in getMaxCpuSets(): " + e); + return null; + } + + return result; + } + + private static void addRange(ArrayList list, String s) { + String[] range = s.split("-"); + if (range.length != 2) { + throw new RuntimeException("Range should only contain two items, but contains " + + range.length + " items"); + } + + int min = Integer.parseInt(range[0]); + int max = Integer.parseInt(range[1]); + + if (min >= max) { + String msg = String.format("min is greater or equals to max, min = %d, max = %d", + min, max); + throw new RuntimeException(msg); + } + + for (int i = min; i <= max; i++) { + list.add(i); + } + } + + + // Convert list of integers to string with comma-separated values + public static String listToString(List list) { + return listToString(list, Integer.MAX_VALUE); + } + + // Convert list of integers to a string with comma-separated values; + // include up to maxCount. + public static String listToString(List list, int maxCount) { + return list.stream() + .limit(maxCount) + .map(Object::toString) + .collect(Collectors.joining(",")); + } + + public static String numberToString(int num) { + return IntStream.range(0, num).boxed().map(Object::toString).collect(Collectors.joining(",")); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/cgroup/MetricsTester.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,597 @@ +/* + * 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 jdk.test.lib.containers.cgroup; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Scanner; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.Stream; +import jdk.internal.platform.Metrics; + +public class MetricsTester { + + private static final double ERROR_MARGIN = 0.1; + private static long unlimited_minimum = 0x7FFFFFFFFF000000L; + long startSysVal; + long startUserVal; + long startUsage; + long startPerCpu[]; + + enum SubSystem { + MEMORY("memory"), + CPUSET("cpuset"), + CPU("cpu"), + CPUACCT("cpuacct"), + BLKIO("blkio"); + + private String value; + + SubSystem(String value) { + this.value = value; + } + + public String value() { + return value; + } + } + + private static final Set allowedSubSystems = + Stream.of(SubSystem.values()).map(SubSystem::value).collect(Collectors.toSet()); + + private static final Map subSystemPaths = new HashMap<>(); + + private static void setPath(String[] line) { + String cgroupPath = line[2]; + String[] subSystems = line[1].split(","); + + for (String subSystem : subSystems) { + if (allowedSubSystems.contains(subSystem)) { + String[] paths = subSystemPaths.get(subSystem); + String finalPath = ""; + String root = paths[0]; + String mountPoint = paths[1]; + if (root != null && cgroupPath != null) { + if (root.equals("/")) { + if (cgroupPath.equals("/")) { + finalPath = mountPoint + cgroupPath; + } else { + finalPath = mountPoint; + } + } else { + if (root.equals(cgroupPath)) { + finalPath = mountPoint; + } else { + if (root.indexOf(cgroupPath) == 0) { + if (cgroupPath.length() > root.length()) { + String cgroupSubstr = cgroupPath.substring(root.length()); + finalPath = mountPoint + cgroupSubstr; + } + } + } + } + } + subSystemPaths.put(subSystem, new String[]{finalPath}); + } + } + } + + private static void createSubsystems(String[] line) { + if (line.length < 5) return; + Path p = Paths.get(line[4]); + String subsystemName = p.getFileName().toString(); + if (subsystemName != null) { + for (String subSystem : subsystemName.split(",")) { + if (allowedSubSystems.contains(subSystem)) { + subSystemPaths.put(subSystem, new String[]{line[3], line[4]}); + } + } + } + } + + public void setup() { + Metrics metrics = Metrics.systemMetrics(); + // Initialize CPU usage metrics before we do any testing. + startSysVal = metrics.getCpuSystemUsage(); + startUserVal = metrics.getCpuUserUsage(); + startUsage = metrics.getCpuUsage(); + startPerCpu = metrics.getPerCpuUsage(); + + try { + Stream lines = Files.lines(Paths.get("/proc/self/mountinfo")); + lines.filter(line -> line.contains(" - cgroup cgroup ")) + .map(line -> line.split(" ")) + .forEach(MetricsTester::createSubsystems); + lines.close(); + + lines = Files.lines(Paths.get("/proc/self/cgroup")); + lines.map(line -> line.split(":")) + .filter(line -> (line.length >= 3)) + .forEach(MetricsTester::setPath); + lines.close(); + } catch (IOException e) { + } + } + + private static String getFileContents(SubSystem subSystem, String fileName) { + String fname = subSystemPaths.get(subSystem.value())[0] + File.separator + fileName; + try { + return new Scanner(new File(fname)).useDelimiter("\\Z").next(); + } catch (FileNotFoundException e) { + System.err.println("Unable to open : " + fname); + return ""; + } + } + + private static long getLongValueFromFile(SubSystem subSystem, String fileName) { + String data = getFileContents(subSystem, fileName); + return data.isEmpty() ? 0L : Long.parseLong(data); + } + + private static long getLongValueFromFile(SubSystem subSystem, String metric, String subMetric) { + String stats = getFileContents(subSystem, metric); + String[] tokens = stats.split("[\\r\\n]+"); + for (int i = 0; i < tokens.length; i++) { + if (tokens[i].startsWith(subMetric)) { + return Long.parseLong(tokens[i].split("\\s+")[1]); + } + } + return 0L; + } + + private static double getDoubleValueFromFile(SubSystem subSystem, String fileName) { + String data = getFileContents(subSystem, fileName); + return data.isEmpty() ? 0.0 : Double.parseDouble(data); + } + + private boolean compareWithErrorMargin(long oldVal, long newVal) { + return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); + } + + private boolean compareWithErrorMargin(double oldVal, double newVal) { + return Math.abs(oldVal - newVal) <= Math.abs(oldVal * ERROR_MARGIN); + } + + private static void fail(SubSystem system, String metric, long oldVal, long testVal) { + throw new RuntimeException("Test failed for - " + system.value + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + private static void fail(SubSystem system, String metric, String oldVal, String testVal) { + throw new RuntimeException("Test failed for - " + system.value + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + private static void fail(SubSystem system, String metric, double oldVal, double testVal) { + throw new RuntimeException("Test failed for - " + system.value + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + private static void fail(SubSystem system, String metric, boolean oldVal, boolean testVal) { + throw new RuntimeException("Test failed for - " + system.value + ":" + + metric + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + private static void warn(SubSystem system, String metric, long oldVal, long testVal) { + System.err.println("Warning - " + system.value + ":" + metric + + ", expected [" + oldVal + "], got [" + testVal + "]"); + } + + public void testMemorySubsystem() { + Metrics metrics = Metrics.systemMetrics(); + + // User Memory + long oldVal = metrics.getMemoryFailCount(); + long newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.failcnt"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.failcnt", oldVal, newVal); + } + + oldVal = metrics.getMemoryLimit(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryMaxUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.max_usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.usage_in_bytes", oldVal, newVal); + } + + // Kernel memory + oldVal = metrics.getKernelMemoryFailCount(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.failcnt"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.failcnt", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryLimit(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryMaxUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getKernelMemoryUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.usage_in_bytes", oldVal, newVal); + } + + //TCP Memory + oldVal = metrics.getTcpMemoryFailCount(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.failcnt"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.tcp.failcnt", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryLimit(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.tcp.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryMaxUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.tcp.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getTcpMemoryUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.kmem.tcp.usage_in_bytes", oldVal, newVal); + } + + // Memory and Swap + oldVal = metrics.getMemoryAndSwapFailCount(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.failcnt"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.memsw.failcnt", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapLimit(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.memsw.limit_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapMaxUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.memsw.max_usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemoryAndSwapUsage(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.memsw.usage_in_bytes"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.memsw.usage_in_bytes", oldVal, newVal); + } + + oldVal = metrics.getMemorySoftLimit(); + newVal = getLongValueFromFile(SubSystem.MEMORY, "memory.soft_limit_in_bytes"); + newVal = newVal > unlimited_minimum ? -1L : newVal; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.MEMORY, "memory.soft_limit_in_bytes", oldVal, newVal); + } + + boolean oomKillEnabled = metrics.isMemoryOOMKillEnabled(); + boolean newOomKillEnabled = getLongValueFromFile(SubSystem.MEMORY, + "memory.oom_control", "oom_kill_disable") == 0L ? true : false; + if (oomKillEnabled != newOomKillEnabled) { + throw new RuntimeException("Test failed for - " + SubSystem.MEMORY.value + ":" + + "memory.oom_control:oom_kill_disable" + ", expected [" + + oomKillEnabled + "], got [" + newOomKillEnabled + "]"); + } + } + + public void testCpuAccounting() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getCpuUsage(); + long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.usage"); + + if (!compareWithErrorMargin(oldVal, newVal)) { + warn(SubSystem.CPUACCT, "cpuacct.usage", oldVal, newVal); + } + + Long[] newVals = Stream.of(getFileContents(SubSystem.CPUACCT, "cpuacct.usage_percpu") + .split("\\s+")) + .map(Long::parseLong) + .toArray(Long[]::new); + Long[] oldVals = LongStream.of(metrics.getPerCpuUsage()).boxed().toArray(Long[]::new); + for (int i = 0; i < oldVals.length; i++) { + if (!compareWithErrorMargin(oldVals[i], newVals[i])) { + warn(SubSystem.CPUACCT, "cpuacct.usage_percpu", oldVals[i], newVals[i]); + } + } + + oldVal = metrics.getCpuUserUsage(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "user"); + if (!compareWithErrorMargin(oldVal, newVal)) { + warn(SubSystem.CPUACCT, "cpuacct.usage - user", oldVal, newVal); + } + + oldVal = metrics.getCpuSystemUsage(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpuacct.stat", "system"); + if (!compareWithErrorMargin(oldVal, newVal)) { + warn(SubSystem.CPUACCT, "cpuacct.usage - system", oldVal, newVal); + } + } + + public void testCpuSchedulingMetrics() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getCpuPeriod(); + long newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_period_us"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.cfs_period_us", oldVal, newVal); + } + + oldVal = metrics.getCpuQuota(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.cfs_quota_us"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.cfs_quota_us", oldVal, newVal); + } + + oldVal = metrics.getCpuShares(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.shares"); + if (newVal == 0 || newVal == 1024) newVal = -1; + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.shares", oldVal, newVal); + } + + oldVal = metrics.getCpuNumPeriods(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_periods"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.stat - nr_periods", oldVal, newVal); + } + + oldVal = metrics.getCpuNumThrottled(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "nr_throttled"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.stat - nr_throttled", oldVal, newVal); + } + + oldVal = metrics.getCpuThrottledTime(); + newVal = getLongValueFromFile(SubSystem.CPUACCT, "cpu.stat", "throttled_time"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.CPUACCT, "cpu.stat - throttled_time", oldVal, newVal); + } + } + + public void testCpuSets() { + Metrics metrics = Metrics.systemMetrics(); + Integer[] oldVal = Arrays.stream(metrics.getCpuSetCpus()).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + + String cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.cpus"); + // Parse range string in the format 1,2-6,7 + Integer[] newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { + if (a.contains("-")) { + String[] range = a.split("-"); + return IntStream.rangeClosed(Integer.parseInt(range[0]), + Integer.parseInt(range[1])).boxed(); + } else { + return Stream.of(Integer.parseInt(a)); + } + }).toArray(Integer[]::new); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(SubSystem.CPUSET, "cpuset.cpus", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + int [] cpuSets = metrics.getEffectiveCpuSetCpus(); + + // Skip this test if this metric is supported on this platform + if (cpuSets.length != 0) { + oldVal = Arrays.stream(cpuSets).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_cpus"); + newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { + if (a.contains("-")) { + String[] range = a.split("-"); + return IntStream.rangeClosed(Integer.parseInt(range[0]), + Integer.parseInt(range[1])).boxed(); + } else { + return Stream.of(Integer.parseInt(a)); + } + }).toArray(Integer[]::new); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(SubSystem.CPUSET, "cpuset.effective_cpus", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + } + + oldVal = Arrays.stream(metrics.getCpuSetMems()).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.mems"); + newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { + if (a.contains("-")) { + String[] range = a.split("-"); + return IntStream.rangeClosed(Integer.parseInt(range[0]), + Integer.parseInt(range[1])).boxed(); + } else { + return Stream.of(Integer.parseInt(a)); + } + }).toArray(Integer[]::new); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(SubSystem.CPUSET, "cpuset.mems", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + + int [] cpuSetMems = metrics.getEffectiveCpuSetMems(); + + // Skip this test if this metric is supported on this platform + if (cpuSetMems.length != 0) { + oldVal = Arrays.stream(cpuSetMems).boxed().toArray(Integer[]::new); + Arrays.sort(oldVal); + cpusstr = getFileContents(SubSystem.CPUSET, "cpuset.effective_mems"); + newVal = Stream.of(cpusstr.split(",")).flatMap(a -> { + if (a.contains("-")) { + String[] range = a.split("-"); + return IntStream.rangeClosed(Integer.parseInt(range[0]), + Integer.parseInt(range[1])).boxed(); + } else { + return Stream.of(Integer.parseInt(a)); + } + }).toArray(Integer[]::new); + Arrays.sort(newVal); + if (Arrays.compare(oldVal, newVal) != 0) { + fail(SubSystem.CPUSET, "cpuset.effective_mems", Arrays.toString(oldVal), + Arrays.toString(newVal)); + } + } + + double oldValue = metrics.getCpuSetMemoryPressure(); + double newValue = getDoubleValueFromFile(SubSystem.CPUSET, "cpuset.memory_pressure"); + if (!compareWithErrorMargin(oldValue, newValue)) { + fail(SubSystem.CPUSET, "cpuset.memory_pressure", oldValue, newValue); + } + + boolean oldV = metrics.isCpuSetMemoryPressureEnabled(); + boolean newV = getLongValueFromFile(SubSystem.CPUSET, + "cpuset.memory_pressure_enabled") == 1 ? true : false; + if (oldV != newV) { + fail(SubSystem.CPUSET, "cpuset.memory_pressure_enabled", oldV, newV); + } + } + + public void testBlkIO() { + Metrics metrics = Metrics.systemMetrics(); + long oldVal = metrics.getBlkIOServiceCount(); + long newVal = getLongValueFromFile(SubSystem.BLKIO, + "blkio.throttle.io_service_bytes", "Total"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.BLKIO, "blkio.throttle.io_service_bytes - Total", + oldVal, newVal); + } + + oldVal = metrics.getBlkIOServiced(); + newVal = getLongValueFromFile(SubSystem.BLKIO, "blkio.throttle.io_serviced", "Total"); + if (!compareWithErrorMargin(oldVal, newVal)) { + fail(SubSystem.BLKIO, "blkio.throttle.io_serviced - Total", oldVal, newVal); + } + } + + public void testCpuConsumption() throws IOException, InterruptedException { + Metrics metrics = Metrics.systemMetrics(); + // make system call + long newSysVal = metrics.getCpuSystemUsage(); + long newUserVal = metrics.getCpuUserUsage(); + long newUsage = metrics.getCpuUsage(); + long[] newPerCpu = metrics.getPerCpuUsage(); + + if (newSysVal <= startSysVal) { + fail(SubSystem.CPU, "getCpuSystemUsage", newSysVal, startSysVal); + } + + if (newUserVal <= startUserVal) { + fail(SubSystem.CPU, "getCpuUserUsage", newUserVal, startUserVal); + } + + if (newUsage <= startUsage) { + fail(SubSystem.CPU, "getCpuUserUsage", newUsage, startUsage); + } + + boolean success = false; + for (int i = 0; i < startPerCpu.length; i++) { + if (newPerCpu[i] > startPerCpu[i]) { + success = true; + break; + } + } + + if(!success) fail(SubSystem.CPU, "getPerCpuUsage", Arrays.toString(newPerCpu), + Arrays.toString(startPerCpu)); + } + + public void testMemoryUsage() throws Exception { + Metrics metrics = Metrics.systemMetrics(); + long memoryMaxUsage = metrics.getMemoryMaxUsage(); + long memoryUsage = metrics.getMemoryUsage(); + + long[] ll = new long[64*1024*1024]; // 64M + + long newMemoryMaxUsage = metrics.getMemoryMaxUsage(); + long newMemoryUsage = metrics.getMemoryUsage(); + + if(newMemoryMaxUsage < memoryMaxUsage) { + fail(SubSystem.MEMORY, "getMemoryMaxUsage", newMemoryMaxUsage, + memoryMaxUsage); + } + + if(newMemoryUsage < memoryUsage) { + fail(SubSystem.MEMORY, "getMemoryUsage", newMemoryUsage, memoryUsage); + } + } + + public static void main(String[] args) throws Exception { + // If cgroups is not configured, report success + Metrics metrics = Metrics.systemMetrics(); + if (metrics == null) { + System.out.println("TEST PASSED!!!"); + return; + } + + MetricsTester metricsTester = new MetricsTester(); + metricsTester.setup(); + metricsTester.testCpuAccounting(); + metricsTester.testCpuSchedulingMetrics(); + metricsTester.testCpuSets(); + metricsTester.testMemorySubsystem(); + metricsTester.testBlkIO(); + metricsTester.testCpuConsumption(); + metricsTester.testMemoryUsage(); + System.out.println("TEST PASSED!!!"); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/docker/Common.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/docker/Common.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.docker; + +/* + * Methods and definitions common to docker tests container in this directory + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; + + +public class Common { + public static final String imageNameAndTag = "jdk-internal:test"; + + public static String imageName(String suffix) { + return imageNameAndTag + "-" + suffix; + } + + + public static void prepareWhiteBox() throws Exception { + Files.copy(Paths.get(new File("whitebox.jar").getAbsolutePath()), + Paths.get(Utils.TEST_CLASSES, "whitebox.jar"), StandardCopyOption.REPLACE_EXISTING); + } + + + // create simple commonly used options + public static DockerRunOptions newOpts(String imageNameAndTag) { + return new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", "-version") + .addJavaOpts("-Xlog:os+container=trace"); + } + + + // create commonly used options with class to be launched inside container + public static DockerRunOptions newOpts(String imageNameAndTag, String testClass) { + DockerRunOptions opts = + new DockerRunOptions(imageNameAndTag, "/jdk/bin/java", testClass); + opts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/"); + opts.addJavaOpts("-Xlog:os+container=trace", "-cp", "/test-classes/"); + return opts; + } + + + public static DockerRunOptions addWhiteBoxOpts(DockerRunOptions opts) { + opts.addJavaOpts("-Xbootclasspath/a:/test-classes/whitebox.jar", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI"); + return opts; + } + + + // most common type of run and checks + public static OutputAnalyzer run(DockerRunOptions opts) throws Exception { + return DockerTestUtils.dockerRunJava(opts) + .shouldHaveExitValue(0).shouldContain("Initializing Container Support"); + } + + + // log beginning of a test case + public static void logNewTestCase(String msg) { + System.out.println("========== NEW TEST CASE: " + msg); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,77 @@ +/* + * 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. + */ + +package jdk.test.lib.containers.docker; + +import java.util.ArrayList; +import java.util.Collections; + + +// This class represents options for running java inside docker containers +// in test environment. +public class DockerRunOptions { + public String imageNameAndTag; + public ArrayList dockerOpts = new ArrayList(); + public String command; // normally a full path to java + public ArrayList javaOpts = new ArrayList(); + public String classToRun; // class or "-version" + public ArrayList classParams = new ArrayList(); + + public boolean tty = true; + public boolean removeContainerAfterUse = true; + public boolean appendTestJavaOptions = true; + public boolean retainChildStdout = false; + + /** + * Convenience constructor for most common use cases in testing. + * @param imageNameAndTag a string representing name and tag for the + * docker image to run, as "name:tag" + * @param javaCmd a java command to run (e.g. /jdk/bin/java) + * @param classToRun a class to run, or "-version" + * @param javaOpts java options to use + * + * @return Default docker run options + */ + public DockerRunOptions(String imageNameAndTag, String javaCmd, + String classToRun, String... javaOpts) { + this.imageNameAndTag = imageNameAndTag; + this.command = javaCmd; + this.classToRun = classToRun; + this.addJavaOpts(javaOpts); + } + + public DockerRunOptions addDockerOpts(String... opts) { + Collections.addAll(dockerOpts, opts); + return this; + } + + public DockerRunOptions addJavaOpts(String... opts) { + Collections.addAll(javaOpts, opts); + return this; + } + + public DockerRunOptions addClassOptions(String... opts) { + Collections.addAll(classParams,opts); + return this; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.docker; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; + + +public class DockerTestUtils { + private static final String FS = File.separator; + private static boolean isDockerEngineAvailable = false; + private static boolean wasDockerEngineChecked = false; + + // Use this property to specify docker location on your system. + // E.g.: "/usr/local/bin/docker". + private static final String DOCKER_COMMAND = + System.getProperty("jdk.test.docker.command", "docker"); + + // Set this property to true to retain image after test. By default + // images are removed after test execution completes. + // Retaining the image can be useful for diagnostics and image inspection. + // E.g.: start image interactively: docker run -it . + public static final boolean RETAIN_IMAGE_AFTER_TEST = + Boolean.getBoolean("jdk.test.docker.retain.image"); + + // Path to a JDK under test. + // This may be useful when developing tests on non-Linux platforms. + public static final String JDK_UNDER_TEST = + System.getProperty("jdk.test.docker.jdk", Utils.TEST_JDK); + + + /** + * Optimized check of whether the docker engine is available in a given + * environment. Checks only once, then remembers the result in a singleton. + * + * @return true if docker engine is available + * @throws Exception + */ + public static boolean isDockerEngineAvailable() throws Exception { + if (wasDockerEngineChecked) + return isDockerEngineAvailable; + + isDockerEngineAvailable = isDockerEngineAvailableCheck(); + wasDockerEngineChecked = true; + return isDockerEngineAvailable; + } + + + /** + * Convenience method, will check if docker engine is available and usable; + * will print the appropriate message when not available. + * + * @return true if docker engine is available + * @throws Exception + */ + public static boolean canTestDocker() throws Exception { + if (isDockerEngineAvailable()) { + return true; + } else { + throw new SkippedException("Docker engine is not available on this system"); + } + } + + + /** + * Simple check - is docker engine available, accessible and usable. + * Run basic docker command: 'docker ps' - list docker instances. + * If docker engine is available and accesible then true is returned + * and we can proceed with testing docker. + * + * @return true if docker engine is available and usable + * @throws Exception + */ + private static boolean isDockerEngineAvailableCheck() throws Exception { + try { + execute(DOCKER_COMMAND, "ps") + .shouldHaveExitValue(0) + .shouldContain("CONTAINER") + .shouldContain("IMAGE"); + } catch (Exception e) { + return false; + } + return true; + } + + + /** + * Build a docker image that contains JDK under test. + * The jdk will be placed under the "/jdk/" folder inside the docker file system. + * + * @param imageName name of the image to be created, including version tag + * @param dockerfile name of the dockerfile residing in the test source; + * we check for a platform specific dockerfile as well + * and use this one in case it exists + * @param buildDirName name of the docker build/staging directory, which will + * be created in the jtreg's scratch folder + * @throws Exception + */ + public static void + buildJdkDockerImage(String imageName, String dockerfile, String buildDirName) + throws Exception { + + Path buildDir = Paths.get(".", buildDirName); + if (Files.exists(buildDir)) { + throw new RuntimeException("The docker build directory already exists: " + buildDir); + } + + Path jdkSrcDir = Paths.get(JDK_UNDER_TEST); + Path jdkDstDir = buildDir.resolve("jdk"); + + Files.createDirectories(jdkDstDir); + + // Copy JDK-under-test tree to the docker build directory. + // This step is required for building a docker image. + Files.walkFileTree(jdkSrcDir, new CopyFileVisitor(jdkSrcDir, jdkDstDir)); + buildDockerImage(imageName, Paths.get(Utils.TEST_SRC, dockerfile), buildDir); + } + + + /** + * Build a docker image based on given docker file and docker build directory. + * + * @param imageName name of the image to be created, including version tag + * @param dockerfile path to the Dockerfile to be used for building the docker + * image. The specified dockerfile will be copied to the docker build + * directory as 'Dockerfile' + * @param buildDir build directory; it should already contain all the content + * needed to build the docker image. + * @throws Exception + */ + public static void + buildDockerImage(String imageName, Path dockerfile, Path buildDir) throws Exception { + + generateDockerFile(buildDir.resolve("Dockerfile"), + DockerfileConfig.getBaseImageName(), + DockerfileConfig.getBaseImageVersion()); + try { + // Build the docker + execute(DOCKER_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString()) + .shouldHaveExitValue(0) + .shouldContain("Successfully built"); + } catch (Exception e) { + // If docker image building fails there is a good chance it happens due to environment and/or + // configuration other than product failure. Throw jtreg skipped exception in such case + // instead of failing the test. + throw new SkippedException("Building docker image failed. Details: \n" + e.getMessage()); + } + } + + + /** + * Build the docker command to run java inside a container + * + * @param DockerRunOptions optins for running docker + * + * @return command + * @throws Exception + */ + public static List buildJavaCommand(DockerRunOptions opts) throws Exception { + List cmd = new ArrayList<>(); + + cmd.add(DOCKER_COMMAND); + cmd.add("run"); + if (opts.tty) + cmd.add("--tty=true"); + if (opts.removeContainerAfterUse) + cmd.add("--rm"); + + cmd.addAll(opts.dockerOpts); + cmd.add(opts.imageNameAndTag); + cmd.add(opts.command); + + cmd.addAll(opts.javaOpts); + if (opts.appendTestJavaOptions) { + Collections.addAll(cmd, Utils.getTestJavaOpts()); + } + + cmd.add(opts.classToRun); + cmd.addAll(opts.classParams); + + return cmd; + } + + /** + * Run Java inside the docker image with specified parameters and options. + * + * @param DockerRunOptions optins for running docker + * + * @return output of the run command + * @throws Exception + */ + public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Exception { + return execute(buildJavaCommand(opts)); + } + + + /** + * Remove docker image + * + * @param DockerRunOptions optins for running docker + * @throws Exception + */ + public static void removeDockerImage(String imageNameAndTag) throws Exception { + execute(DOCKER_COMMAND, "rmi", "--force", imageNameAndTag); + } + + + + /** + * Convenience method - express command as sequence of strings + * + * @param command to execute + * @return The output from the process + * @throws Exception + */ + public static OutputAnalyzer execute(List command) throws Exception { + return execute(command.toArray(new String[command.size()])); + } + + + /** + * Execute a specified command in a process, report diagnostic info. + * + * @param command to be executed + * @return The output from the process + * @throws Exception + */ + public static OutputAnalyzer execute(String... command) throws Exception { + + ProcessBuilder pb = new ProcessBuilder(command); + System.out.println("[COMMAND]\n" + Utils.getCommandLine(pb)); + + long started = System.currentTimeMillis(); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]"); + System.out.println("[STDERR]\n" + output.getStderr()); + System.out.println("[STDOUT]\n" + output.getStdout()); + + return output; + } + + + private static void generateDockerFile(Path dockerfile, String baseImage, + String baseImageVersion) throws Exception { + String template = + "FROM %s:%s\n" + + "COPY /jdk /jdk\n" + + "ENV JAVA_HOME=/jdk\n" + + "CMD [\"/bin/bash\"]\n"; + String dockerFileStr = String.format(template, baseImage, baseImageVersion); + Files.writeString(dockerfile, dockerFileStr); + } + + + private static class CopyFileVisitor extends SimpleFileVisitor { + private final Path src; + private final Path dst; + + public CopyFileVisitor(Path src, Path dst) { + this.src = src; + this.dst = dst; + } + + + @Override + public FileVisitResult preVisitDirectory(Path file, + BasicFileAttributes attrs) throws IOException { + Path dstDir = dst.resolve(src.relativize(file)); + if (!dstDir.toFile().exists()) { + Files.createDirectories(dstDir); + } + return FileVisitResult.CONTINUE; + } + + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attrs) throws IOException { + if (!file.toFile().isFile()) { + return FileVisitResult.CONTINUE; + } + Path dstFile = dst.resolve(src.relativize(file)); + Files.copy(file, dstFile, StandardCopyOption.COPY_ATTRIBUTES); + return FileVisitResult.CONTINUE; + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.containers.docker; + +import jdk.test.lib.Platform; + +// Use the following properties to specify docker base image at test execution time: +// Image name: jdk.test.docker.image.name +// Image version: jdk.test.docker.image.version +// Usage: +// jtreg -Djdk.test.docker.image.name= -Djdk.test.docker.image.version= test/hotspot/jtreg/runtime/containers/docker/ +// E.g.: +// jtreg -Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest test/hotspot/jtreg/runtime/containers/docker/ +// Using make: +// make test TEST="test/hotspot/jtreg/runtime/containers/docker" JTREG="JAVA_OPTIONS=-Djdk.test.docker.image.name=ubuntu -Djdk.test.docker.image.version=latest" +// Note: base image version should not be an empty string. Use "latest" to get the latest version. + +public class DockerfileConfig { + static String getBaseImageName() { + String name = System.getProperty("jdk.test.docker.image.name"); + if (name != null) { + System.out.println("DockerfileConfig: using custom image name: " + name); + return name; + } + + switch (Platform.getOsArch()) { + case "aarch64": + return "arm64v8/ubuntu"; + case "ppc64le": + return "ppc64le/ubuntu"; + case "s390x": + return "s390x/ubuntu"; + default: + return "oraclelinux"; + } + } + + static String getBaseImageVersion() { + String version = System.getProperty("jdk.test.docker.image.version"); + if (version != null) { + System.out.println("DockerfileConfig: using custom image version: " + version); + return version; + } + + switch (Platform.getOsArch()) { + case "aarch64": + case "ppc64le": + case "s390x": + return "latest"; + default: + return "7.6"; + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/CommandExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/CommandExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import jdk.test.lib.process.OutputAnalyzer; + +/** + * Abstract base class for Diagnostic Command executors + */ +public abstract class CommandExecutor { + + /** + * Execute a diagnostic command + * + * @param cmd The diagnostic command to execute + * @return an {@link jdk.test.lib.process.OutputAnalyzer} encapsulating the output of the command + * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the + * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in + * stderr, regardless of the specific executor used. + */ + public final OutputAnalyzer execute(String cmd) throws CommandExecutorException { + return execute(cmd, false); + } + + /** + * Execute a diagnostic command + * + * @param cmd The diagnostic command to execute + * @param silent Do not print the command output + * @return an {@link jdk.test.lib.process.OutputAnalyzer} encapsulating the output of the command + * @throws CommandExecutorException if there is an exception on the "calling side" while trying to execute the + * Diagnostic Command. Exceptions thrown on the remote side are available as textual representations in + * stderr, regardless of the specific executor used. + */ + public final OutputAnalyzer execute(String cmd, boolean silent) throws CommandExecutorException { + if (!silent) { + System.out.printf("Running DCMD '%s' through '%s'%n", cmd, this.getClass().getSimpleName()); + } + + OutputAnalyzer oa = executeImpl(cmd); + + if (!silent) { + System.out.println("---------------- stdout ----------------"); + System.out.println(oa.getStdout()); + System.out.println("---------------- stderr ----------------"); + System.out.println(oa.getStderr()); + System.out.println("----------------------------------------"); + System.out.println(); + } + return oa; + } + + protected abstract OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/CommandExecutorException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/CommandExecutorException.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +/** + * CommandExecutorException encapsulates exceptions thrown (on the "calling side") from the execution of Diagnostic + * Commands + */ +public class CommandExecutorException extends RuntimeException { + private static final long serialVersionUID = -7039597746579144280L; + + public CommandExecutorException(String message, Throwable e) { + super(message, e); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/FileJcmdExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/FileJcmdExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool and its ability to read + * Diagnostic Commands from a file. + */ +public class FileJcmdExecutor extends PidJcmdExecutor { + + /** + * Instantiates a new FileJcmdExecutor targeting the current VM + */ + public FileJcmdExecutor() { + super(); + } + + /** + * Instantiates a new FileJcmdExecutor targeting the VM indicated by the given pid + * + * @param target Pid of the target VM + */ + public FileJcmdExecutor(String target) { + super(target); + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + File cmdFile = createTempFile(); + writeCommandToTemporaryFile(cmd, cmdFile); + + return Arrays.asList(jcmdBinary, Long.toString(pid), + "-f", cmdFile.getAbsolutePath()); + } + + private void writeCommandToTemporaryFile(String cmd, File cmdFile) { + try (PrintWriter pw = new PrintWriter(cmdFile)) { + pw.println(cmd); + } catch (IOException e) { + String message = "Could not write to file: " + cmdFile.getAbsolutePath(); + throw new CommandExecutorException(message, e); + } + } + + private File createTempFile() { + try { + File cmdFile = File.createTempFile("input", "jcmd"); + cmdFile.deleteOnExit(); + return cmdFile; + } catch (IOException e) { + throw new CommandExecutorException("Could not create temporary file", e); + } + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/JMXExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/JMXExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import jdk.test.lib.process.OutputAnalyzer; + +import javax.management.*; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXServiceURL; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; + +import java.lang.management.ManagementFactory; + +import java.util.HashMap; + +/** + * Executes Diagnostic Commands on the target VM (specified by a host/port combination or a full JMX Service URL) using + * the JMX interface. If the target is not the current VM, the JMX Remote interface must be enabled beforehand. + */ +public class JMXExecutor extends CommandExecutor { + + private final MBeanServerConnection mbs; + + /** + * Instantiates a new JMXExecutor targeting the current VM + */ + public JMXExecutor() { + super(); + mbs = ManagementFactory.getPlatformMBeanServer(); + } + + /** + * Instantiates a new JMXExecutor targeting the VM indicated by the given host/port combination or a full JMX + * Service URL + * + * @param target a host/port combination on the format "host:port" or a full JMX Service URL of the target VM + */ + public JMXExecutor(String target) { + String urlStr; + + if (target.matches("^\\w[\\w\\-]*(\\.[\\w\\-]+)*:\\d+$")) { + /* Matches "hostname:port" */ + urlStr = String.format("service:jmx:rmi:///jndi/rmi://%s/jmxrmi", target); + } else if (target.startsWith("service:")) { + urlStr = target; + } else { + throw new IllegalArgumentException("Could not recognize target string: " + target); + } + + try { + JMXServiceURL url = new JMXServiceURL(urlStr); + JMXConnector c = JMXConnectorFactory.connect(url, new HashMap<>()); + mbs = c.getMBeanServerConnection(); + } catch (IOException e) { + throw new CommandExecutorException("Could not initiate connection to target: " + target, e); + } + } + + protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException { + String stdout = ""; + String stderr = ""; + + String[] cmdParts = cmd.split(" ", 2); + String operation = commandToMethodName(cmdParts[0]); + Object[] dcmdArgs = produceArguments(cmdParts); + String[] signature = {String[].class.getName()}; + + ObjectName beanName = getMBeanName(); + + try { + stdout = (String) mbs.invoke(beanName, operation, dcmdArgs, signature); + } + + /* Failures on the "local" side, the one invoking the command. */ + catch (ReflectionException e) { + Throwable cause = e.getCause(); + if (cause instanceof NoSuchMethodException) { + /* We want JMXExecutor to match the behavior of the other CommandExecutors */ + String message = "Unknown diagnostic command: " + operation; + stderr = exceptionTraceAsString(new IllegalArgumentException(message, e)); + } else { + rethrowExecutorException(operation, dcmdArgs, e); + } + } + + /* Failures on the "local" side, the one invoking the command. */ + catch (InstanceNotFoundException | IOException e) { + rethrowExecutorException(operation, dcmdArgs, e); + } + + /* Failures on the remote side, the one executing the invoked command. */ + catch (MBeanException e) { + stdout = exceptionTraceAsString(e); + } + + return new OutputAnalyzer(stdout, stderr); + } + + private void rethrowExecutorException(String operation, Object[] dcmdArgs, + Exception e) throws CommandExecutorException { + String message = String.format("Could not invoke: %s %s", operation, + String.join(" ", (String[]) dcmdArgs[0])); + throw new CommandExecutorException(message, e); + } + + private ObjectName getMBeanName() throws CommandExecutorException { + String MBeanName = "com.sun.management:type=DiagnosticCommand"; + + try { + return new ObjectName(MBeanName); + } catch (MalformedObjectNameException e) { + String message = "MBean not found: " + MBeanName; + throw new CommandExecutorException(message, e); + } + } + + private Object[] produceArguments(String[] cmdParts) { + Object[] dcmdArgs = {new String[0]}; /* Default: No arguments */ + + if (cmdParts.length == 2) { + dcmdArgs[0] = cmdParts[1].split(" "); + } + return dcmdArgs; + } + + /** + * Convert from diagnostic command to MBean method name + * + * Examples: + * help --> help + * VM.version --> vmVersion + * VM.command_line --> vmCommandLine + */ + private static String commandToMethodName(String cmd) { + String operation = ""; + boolean up = false; /* First letter is to be lower case */ + + /* + * If a '.' or '_' is encountered it is not copied, + * instead the next character will be converted to upper case + */ + for (char c : cmd.toCharArray()) { + if (('.' == c) || ('_' == c)) { + up = true; + } else if (up) { + operation = operation.concat(Character.toString(c).toUpperCase()); + up = false; + } else { + operation = operation.concat(Character.toString(c).toLowerCase()); + } + } + + return operation; + } + + private static String exceptionTraceAsString(Throwable cause) { + StringWriter sw = new StringWriter(); + cause.printStackTrace(new PrintWriter(sw)); + return sw.toString(); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/JcmdExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/JcmdExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.util.List; + +/** + * Base class for Diagnostic Command Executors using the jcmd tool + */ +public abstract class JcmdExecutor extends CommandExecutor { + protected String jcmdBinary; + + protected abstract List createCommandLine(String cmd) throws CommandExecutorException; + + protected JcmdExecutor() { + jcmdBinary = JDKToolFinder.getJDKTool("jcmd"); + } + + protected OutputAnalyzer executeImpl(String cmd) throws CommandExecutorException { + List commandLine = createCommandLine(cmd); + + try { + System.out.printf("Executing command '%s'%n", commandLine); + OutputAnalyzer output = ProcessTools.executeProcess(new ProcessBuilder(commandLine)); + System.out.printf("Command returned with exit code %d%n", output.getExitValue()); + + return output; + } catch (Exception e) { + String message = String.format("Caught exception while executing '%s'", commandLine); + throw new CommandExecutorException(message, e); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/MainClassJcmdExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/MainClassJcmdExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by main class) using the jcmd tool + */ +public class MainClassJcmdExecutor extends JcmdExecutor { + private final String mainClass; + + /** + * Instantiates a new MainClassJcmdExecutor targeting the current VM + */ + public MainClassJcmdExecutor() { + super(); + mainClass = System.getProperty("sun.java.command").split(" ")[0]; + } + + /** + * Instantiates a new MainClassJcmdExecutor targeting the VM indicated by the given main class + * + * @param target Main class of the target VM + */ + public MainClassJcmdExecutor(String target) { + super(); + mainClass = target; + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + return Arrays.asList(jcmdBinary, mainClass, cmd); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/dcmd/PidJcmdExecutor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/dcmd/PidJcmdExecutor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.dcmd; + +import jdk.test.lib.process.ProcessTools; + +import java.util.Arrays; +import java.util.List; + +/** + * Executes Diagnostic Commands on the target VM (specified by pid) using the jcmd tool + */ +public class PidJcmdExecutor extends JcmdExecutor { + protected final long pid; + + /** + * Instantiates a new PidJcmdExecutor targeting the current VM + */ + public PidJcmdExecutor() { + super(); + try { + pid = ProcessTools.getProcessId(); + } catch (Exception e) { + throw new CommandExecutorException("Could not determine own pid", e); + } + } + + /** + * Instantiates a new PidJcmdExecutor targeting the VM indicated by the given pid + * + * @param target Pid of the target VM + */ + public PidJcmdExecutor(String target) { + super(); + pid = Long.valueOf(target); + } + + protected List createCommandLine(String cmd) throws CommandExecutorException { + return Arrays.asList(jcmdBinary, Long.toString(pid), cmd); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/HprofParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/HprofParser.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.hprof; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.PrintStream; + +import jdk.test.lib.hprof.model.Snapshot; +import jdk.test.lib.hprof.parser.Reader; + +/** + * Helper class to parse a java heap dump file. + */ +public class HprofParser { + + public static void main(String[] args) throws Exception { + if (args.length < 1) { + System.out.println("No arguments supplied"); + } + File dump = new File(args[0]); + if (!dump.exists() || !dump.isFile()) { + throw new RuntimeException("The dump file does not exist or not a file"); + } + parse(dump); + } + + /** + * @see #parse(File, boolean, boolean, boolean) + */ + public static File parse(File dump) throws Exception { + return parse(dump, false, true, true); + } + + /** + * @see #parse(File, boolean, boolean, boolean) + */ + public static File parseWithDebugInfo(File dump) throws Exception { + return parse(dump, true, true, true); + } + + /** + * Parse a java heap dump file + * + * @param dump Heap dump file to parse + * @param debug Turn on/off debug file parsing + * @param callStack Turn on/off tracking of object allocation call stack + * @param calculateRefs Turn on/off tracking object allocation call stack + * @throws Exception + * @return File containing output from the parser + */ + public static File parse(File dump, boolean debug, boolean callStack, boolean calculateRefs) throws Exception { + File out = new File("hprof." + System.currentTimeMillis() + ".out"); + if (out.exists()) { + out.delete(); + } + + PrintStream psSystemOut = System.out; + try (PrintStream psHprof = new PrintStream(new BufferedOutputStream(new FileOutputStream(out.getAbsolutePath())))) { + System.setOut(psHprof); + + int debugLevel = debug ? 2 : 0; + try (Snapshot snapshot = Reader.readFile(dump.getAbsolutePath(), callStack, debugLevel)) { + System.out.println("Snapshot read, resolving..."); + snapshot.resolve(calculateRefs); + System.out.println("Snapshot resolved."); + } + } finally { + System.setOut(psSystemOut); + } + + return out; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/README Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,13 @@ +The jhat tool has been removed. jhat hprof file parser/validator +are needed for tests. The old packages for jhat were moved here: +com.sun.tools.hat.internal.model -> jdk.test.lib.hprof.model +com.sun.tools.hat.internal.parser -> jdk.test.lib.hprof.parser +com.sun.tools.hat.internal.util -> jdk.test.lib.hprof.util + +jhat was added in JDK 6 and its original implementation was from +java.net HAT project [1]. jhat is an experimental, unsupported tool. +There hasn't been much update to jhat tool in the JDK. In addition, +there are several better heap dump visualizer/analyzer emerged since +JDK 5/6 serviceability support. + +[1] https://java.net/projects/hat diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/AbstractJavaHeapObjectVisitor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects() + * + */ + + +abstract public class AbstractJavaHeapObjectVisitor + implements JavaHeapObjectVisitor { + abstract public void visit(JavaHeapObject other); + + /** + * Should the given field be excluded from the set of things visited? + * @return true if it should. + */ + public boolean exclude(JavaClass clazz, JavaField f) { + return false; + } + + /** + * @return true iff exclude might ever return true + */ + public boolean mightExclude() { + return false; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/ArrayTypeCodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/ArrayTypeCodes.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Primitive array type codes as defined by VM specification. + * + */ +public interface ArrayTypeCodes { + // Typecodes for array elements. + // Refer to newarray instruction in VM Spec. + public static final int T_BOOLEAN = 4; + public static final int T_CHAR = 5; + public static final int T_FLOAT = 6; + public static final int T_DOUBLE = 7; + public static final int T_BYTE = 8; + public static final int T_SHORT = 9; + public static final int T_INT = 10; + public static final int T_LONG = 11; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/HackJavaValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/HackJavaValue.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * This is used to represent values that the program doesn't really understand. + * This includes the null vlaue, and unresolved references (which shouldn't + * happen in well-formed hprof files). + * + * + * @author Bill Foote + */ + + + + +public class HackJavaValue extends JavaValue { + + private String value; + private long size; + + public HackJavaValue(String value, long size) { + this.value = value; + this.size = size; + } + + public String toString() { + return value; + } + + @Override + public long getSize() { + return size; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaBoolean.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaBoolean.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a boolean (i.e. a boolean field in an instance). + * + * @author Bill Foote + */ + + +public class JavaBoolean extends JavaValue { + + boolean value; + + public JavaBoolean(boolean value) { + this.value = value; + } + + public String toString() { + return "" + value; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaByte.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaByte.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents an byte (i.e. a byte field in an instance). + * + * @author Bill Foote + */ + + +public class JavaByte extends JavaValue { + + byte value; + + public JavaByte(byte value) { + this.value = value; + } + + public String toString() { + return "0x" + Integer.toString(((int) value) & 0xff, 16); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaChar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaChar.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a char (i.e. a char field in an instance). + * + * @author Bill Foote + */ + + +public class JavaChar extends JavaValue { + + char value; + + public JavaChar(char value) { + this.value = value; + } + + public String toString() { + return "" + value; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaClass.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,504 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.util.Vector; +import java.util.Enumeration; +import jdk.test.lib.hprof.util.CompositeEnumeration; +import jdk.test.lib.hprof.parser.ReadBuffer; + +/** + * + * @author Bill Foote + */ + + +public class JavaClass extends JavaHeapObject { + // my id + private long id; + // my name + private String name; + + // These are JavaObjectRef before resolve + private JavaThing superclass; + private JavaThing loader; + private JavaThing signers; + private JavaThing protectionDomain; + + // non-static fields + private JavaField[] fields; + // static fields + private JavaStatic[] statics; + + private static final JavaClass[] EMPTY_CLASS_ARRAY = new JavaClass[0]; + // my subclasses + private JavaClass[] subclasses = EMPTY_CLASS_ARRAY; + + // my instances + private Vector instances = new Vector(); + + // Who I belong to. Set on resolve. + private Snapshot mySnapshot; + + // Size of an instance, including VM overhead + private int instanceSize; + // Total number of fields including inherited ones + private int totalNumFields; + + + public JavaClass(long id, String name, long superclassId, long loaderId, + long signersId, long protDomainId, + JavaField[] fields, JavaStatic[] statics, + int instanceSize) { + this.id = id; + this.name = name; + this.superclass = new JavaObjectRef(superclassId); + this.loader = new JavaObjectRef(loaderId); + this.signers = new JavaObjectRef(signersId); + this.protectionDomain = new JavaObjectRef(protDomainId); + this.fields = fields; + this.statics = statics; + this.instanceSize = instanceSize; + } + + public JavaClass(String name, long superclassId, long loaderId, + long signersId, long protDomainId, + JavaField[] fields, JavaStatic[] statics, + int instanceSize) { + this(-1L, name, superclassId, loaderId, signersId, + protDomainId, fields, statics, instanceSize); + } + + public final JavaClass getClazz() { + return mySnapshot.getJavaLangClass(); + } + + public final int getIdentifierSize() { + return mySnapshot.getIdentifierSize(); + } + + public final int getMinimumObjectSize() { + return mySnapshot.getMinimumObjectSize(); + } + + public void resolve(Snapshot snapshot) { + if (mySnapshot != null) { + return; + } + mySnapshot = snapshot; + resolveSuperclass(snapshot); + if (superclass != null) { + ((JavaClass) superclass).addSubclass(this); + } + + loader = loader.dereference(snapshot, null); + signers = signers.dereference(snapshot, null); + protectionDomain = protectionDomain.dereference(snapshot, null); + + for (int i = 0; i < statics.length; i++) { + statics[i].resolve(this, snapshot); + } + snapshot.getJavaLangClass().addInstance(this); + super.resolve(snapshot); + return; + } + + /** + * Resolve our superclass. This might be called well before + * all instances are available (like when reading deferred + * instances in a 1.2 dump file :-) Calling this is sufficient + * to be able to explore this class' fields. + */ + public void resolveSuperclass(Snapshot snapshot) { + if (superclass == null) { + // We must be java.lang.Object, so we have no superclass. + } else { + totalNumFields = fields.length; + superclass = superclass.dereference(snapshot, null); + if (superclass == snapshot.getNullThing()) { + superclass = null; + } else { + try { + JavaClass sc = (JavaClass) superclass; + sc.resolveSuperclass(snapshot); + totalNumFields += sc.totalNumFields; + } catch (ClassCastException ex) { + System.out.println("Warning! Superclass of " + name + " is " + superclass); + superclass = null; + } + } + } + } + + public boolean isString() { + return mySnapshot.getJavaLangString() == this; + } + + public boolean isClassLoader() { + return mySnapshot.getJavaLangClassLoader().isAssignableFrom(this); + } + + /** + * Get a numbered field from this class + */ + public JavaField getField(int i) { + if (i < 0 || i >= fields.length) { + throw new Error("No field " + i + " for " + name); + } + return fields[i]; + } + + /** + * Get the total number of fields that are part of an instance of + * this class. That is, include superclasses. + */ + public int getNumFieldsForInstance() { + return totalNumFields; + } + + /** + * Get a numbered field from all the fields that are part of instance + * of this class. That is, include superclasses. + */ + public JavaField getFieldForInstance(int i) { + if (superclass != null) { + JavaClass sc = (JavaClass) superclass; + if (i < sc.totalNumFields) { + return sc.getFieldForInstance(i); + } + i -= sc.totalNumFields; + } + return getField(i); + } + + /** + * Get the class responsible for field i, where i is a field number that + * could be passed into getFieldForInstance. + * + * @see JavaClass.getFieldForInstance() + */ + public JavaClass getClassForField(int i) { + if (superclass != null) { + JavaClass sc = (JavaClass) superclass; + if (i < sc.totalNumFields) { + return sc.getClassForField(i); + } + } + return this; + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public boolean isArray() { + return name.indexOf('[') != -1; + } + + public Enumeration getInstances(boolean includeSubclasses) { + if (includeSubclasses) { + Enumeration res = instances.elements(); + for (int i = 0; i < subclasses.length; i++) { + res = new CompositeEnumeration(res, + subclasses[i].getInstances(true)); + } + return res; + } else { + return instances.elements(); + } + } + + /** + * @return a count of the instances of this class + */ + public int getInstancesCount(boolean includeSubclasses) { + int result = instances.size(); + if (includeSubclasses) { + for (int i = 0; i < subclasses.length; i++) { + result += subclasses[i].getInstancesCount(includeSubclasses); + } + } + return result; + } + + public JavaClass[] getSubclasses() { + return subclasses; + } + + /** + * This can only safely be called after resolve() + */ + public JavaClass getSuperclass() { + return (JavaClass) superclass; + } + + /** + * This can only safely be called after resolve() + */ + public JavaThing getLoader() { + return loader; + } + + /** + * This can only safely be called after resolve() + */ + public boolean isBootstrap() { + return loader == mySnapshot.getNullThing(); + } + + /** + * This can only safely be called after resolve() + */ + public JavaThing getSigners() { + return signers; + } + + /** + * This can only safely be called after resolve() + */ + public JavaThing getProtectionDomain() { + return protectionDomain; + } + + public JavaField[] getFields() { + return fields; + } + + /** + * Includes superclass fields + */ + public JavaField[] getFieldsForInstance() { + Vector v = new Vector(); + addFields(v); + JavaField[] result = new JavaField[v.size()]; + for (int i = 0; i < v.size(); i++) { + result[i] = v.elementAt(i); + } + return result; + } + + + public JavaStatic[] getStatics() { + return statics; + } + + // returns value of static field of given name + public JavaThing getStaticField(String name) { + for (int i = 0; i < statics.length; i++) { + JavaStatic s = statics[i]; + if (s.getField().getName().equals(name)) { + return s.getValue(); + } + } + return null; + } + + public String toString() { + return "class " + name; + } + + public int compareTo(JavaThing other) { + if (other instanceof JavaClass) { + return name.compareTo(((JavaClass) other).name); + } + return super.compareTo(other); + } + + + /** + * @return true iff a variable of type this is assignable from an instance + * of other + */ + public boolean isAssignableFrom(JavaClass other) { + if (this == other) { + return true; + } else if (other == null) { + return false; + } else { + return isAssignableFrom((JavaClass) other.superclass); + // Trivial tail recursion: I have faith in javac. + } + } + + /** + * Describe the reference that this thing has to target. This will only + * be called if target is in the array returned by getChildrenForRootset. + */ + public String describeReferenceTo(JavaThing target, Snapshot ss) { + for (int i = 0; i < statics.length; i++) { + JavaField f = statics[i].getField(); + if (f.hasId()) { + JavaThing other = statics[i].getValue(); + if (other == target) { + return "static field " + f.getName(); + } + } + } + return super.describeReferenceTo(target, ss); + } + + /** + * @return the size of an instance of this class. Gives 0 for an array + * type. + */ + public int getInstanceSize() { + return instanceSize + mySnapshot.getMinimumObjectSize(); + } + + + /** + * @return The size of all instances of this class. Correctly handles + * arrays. + */ + public long getTotalInstanceSize() { + int count = instances.size(); + if (count == 0 || !isArray()) { + return count * instanceSize; + } + + // array class and non-zero count, we have to + // get the size of each instance and sum it + long result = 0; + for (int i = 0; i < count; i++) { + JavaThing t = (JavaThing) instances.elementAt(i); + result += t.getSize(); + } + return result; + } + + /** + * @return the size of this object + */ + @Override + public long getSize() { + JavaClass cl = mySnapshot.getJavaLangClass(); + if (cl == null) { + return 0; + } else { + return cl.getInstanceSize(); + } + } + + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + super.visitReferencedObjects(v); + JavaHeapObject sc = getSuperclass(); + if (sc != null) v.visit(getSuperclass()); + + JavaThing other; + other = getLoader(); + if (other instanceof JavaHeapObject) { + v.visit((JavaHeapObject)other); + } + other = getSigners(); + if (other instanceof JavaHeapObject) { + v.visit((JavaHeapObject)other); + } + other = getProtectionDomain(); + if (other instanceof JavaHeapObject) { + v.visit((JavaHeapObject)other); + } + + for (int i = 0; i < statics.length; i++) { + JavaField f = statics[i].getField(); + if (!v.exclude(this, f) && f.hasId()) { + other = statics[i].getValue(); + if (other instanceof JavaHeapObject) { + v.visit((JavaHeapObject) other); + } + } + } + } + + // package-privates below this point + final ReadBuffer getReadBuffer() { + return mySnapshot.getReadBuffer(); + } + + final void setNew(JavaHeapObject obj, boolean flag) { + mySnapshot.setNew(obj, flag); + } + + final boolean isNew(JavaHeapObject obj) { + return mySnapshot.isNew(obj); + } + + final StackTrace getSiteTrace(JavaHeapObject obj) { + return mySnapshot.getSiteTrace(obj); + } + + final void addReferenceFromRoot(Root root, JavaHeapObject obj) { + mySnapshot.addReferenceFromRoot(root, obj); + } + + final Root getRoot(JavaHeapObject obj) { + return mySnapshot.getRoot(obj); + } + + final Snapshot getSnapshot() { + return mySnapshot; + } + + void addInstance(JavaHeapObject inst) { + instances.addElement(inst); + } + + // Internals only below this point + private void addFields(Vector v) { + if (superclass != null) { + ((JavaClass) superclass).addFields(v); + } + for (int i = 0; i < fields.length; i++) { + v.addElement(fields[i]); + } + } + + private void addSubclassInstances(Vector v) { + for (int i = 0; i < subclasses.length; i++) { + subclasses[i].addSubclassInstances(v); + } + for (int i = 0; i < instances.size(); i++) { + v.addElement(instances.elementAt(i)); + } + } + + private void addSubclass(JavaClass sub) { + JavaClass newValue[] = new JavaClass[subclasses.length + 1]; + System.arraycopy(subclasses, 0, newValue, 0, subclasses.length); + newValue[subclasses.length] = sub; + subclasses = newValue; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaDouble.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaDouble.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a double (i.e. a double field in an instance). + * + * @author Bill Foote + */ + + +public class JavaDouble extends JavaValue { + + double value; + + public JavaDouble(double value) { + this.value = value; + } + + public String toString() { + return Double.toString(value); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaField.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + + +/** + * + * @author Bill Foote + */ + +public class JavaField { + + private String name; + private String signature; + + public JavaField(String name, String signature) { + this.name = name; + this.signature = signature; + } + + + /** + * @return true if the type of this field is something that has an ID. + * int fields, for exampe, don't. + */ + public boolean hasId() { + char ch = signature.charAt(0); + return (ch == '[' || ch == 'L'); + } + + public String getName() { + return name; + } + + public String getSignature() { + return signature; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaFloat.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaFloat.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a float (i.e. a float field in an instance). + * + * @author Bill Foote + */ + + +public class JavaFloat extends JavaValue { + + float value; + + public JavaFloat(float value) { + this.value = value; + } + + public String toString() { + return Float.toString(value); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaHeapObject.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import jdk.test.lib.hprof.util.Misc; + + +/** + * + * @author Bill Foote + */ + +/** + * Represents an object that's allocated out of the Java heap. It occupies + * memory in the VM, and is the sort of thing that in a JDK 1.1 VM had + * a handle. It can be a + * JavaClass, a JavaObjectArray, a JavaValueArray or a JavaObject. + */ + +public abstract class JavaHeapObject extends JavaThing { + + // + // Who we refer to. This is heavily optimized for space, because it's + // well worth trading a bit of speed for less swapping. + // referers and referersLen go through two phases: Building and + // resolved. When building, referers might have duplicates, but can + // be appended to. When resolved, referers has no duplicates or + // empty slots. + // + private JavaThing[] referers = null; + private int referersLen = 0; // -1 when resolved + + public abstract JavaClass getClazz(); + public abstract long getSize(); + public abstract long getId(); + + /** + * Do any initialization this thing needs after its data is read in. + * Subclasses that override this should call super.resolve(). + */ + public void resolve(Snapshot snapshot) { + StackTrace trace = snapshot.getSiteTrace(this); + if (trace != null) { + trace.resolve(snapshot); + } + } + + // + // Eliminate duplicates from referers, and size the array exactly. + // This sets us up to answer queries. See the comments around the + // referers data member for details. + // + void setupReferers() { + if (referersLen > 1) { + // Copy referers to map, screening out duplicates + Map map = new HashMap(); + for (int i = 0; i < referersLen; i++) { + if (map.get(referers[i]) == null) { + map.put(referers[i], referers[i]); + } + } + + // Now copy into the array + referers = new JavaThing[map.size()]; + map.keySet().toArray(referers); + } + referersLen = -1; + } + + + /** + * @return the id of this thing as hex string + */ + public String getIdString() { + return Misc.toHex(getId()); + } + + public String toString() { + return getClazz().getName() + "@" + getIdString(); + } + + /** + * @return the StackTrace of the point of allocation of this object, + * or null if unknown + */ + public StackTrace getAllocatedFrom() { + return getClazz().getSiteTrace(this); + } + + public boolean isNew() { + return getClazz().isNew(this); + } + + void setNew(boolean flag) { + getClazz().setNew(this, flag); + } + + /** + * Tell the visitor about all of the objects we refer to + */ + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + v.visit(getClazz()); + } + + void addReferenceFrom(JavaHeapObject other) { + if (referersLen == 0) { + referers = new JavaThing[1]; // It was null + } else if (referersLen == referers.length) { + JavaThing[] copy = new JavaThing[(3 * (referersLen + 1)) / 2]; + System.arraycopy(referers, 0, copy, 0, referersLen); + referers = copy; + } + referers[referersLen++] = other; + // We just append to referers here. Measurements have shown that + // around 10% to 30% are duplicates, so it's better to just append + // blindly and screen out all the duplicates at once. + } + + void addReferenceFromRoot(Root r) { + getClazz().addReferenceFromRoot(r, this); + } + + /** + * If the rootset includes this object, return a Root describing one + * of the reasons why. + */ + public Root getRoot() { + return getClazz().getRoot(this); + } + + /** + * Tell who refers to us. + * + * @return an Enumeration of JavaHeapObject instances + */ + public Enumeration getReferers() { + if (referersLen != -1) { + throw new RuntimeException("not resolved: " + getIdString()); + } + return new Enumeration() { + + private int num = 0; + + public boolean hasMoreElements() { + return referers != null && num < referers.length; + } + + public JavaThing nextElement() { + return referers[num++]; + } + }; + } + + /** + * Given other, which the caller promises is in referers, determines if + * the reference is only a weak reference. + */ + public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) { + return false; + } + + /** + * Describe the reference that this thing has to target. This will only + * be called if target is in the array returned by getChildrenForRootset. + */ + public String describeReferenceTo(JavaThing target, Snapshot ss) { + return "??"; + } + + public boolean isHeapAllocated() { + return true; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaHeapObjectVisitor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * A visitor for a JavaThing. @see JavaObject#visitReferencedObjects() + * + * @author Bill Foote + */ + + +public interface JavaHeapObjectVisitor { + public void visit(JavaHeapObject other); + + /** + * Should the given field be excluded from the set of things visited? + * @return true if it should. + */ + public boolean exclude(JavaClass clazz, JavaField f); + + /** + * @return true iff exclude might ever return true + */ + public boolean mightExclude(); +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaInt.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaInt.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents an integer (i.e. an int field in an instance). + * + * @author Bill Foote + */ + + +public class JavaInt extends JavaValue { + + int value; + + public JavaInt(int value) { + this.value = value; + } + + public String toString() { + return "" + value; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaLazyReadObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaLazyReadObject.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.io.IOException; +import jdk.test.lib.hprof.parser.ReadBuffer; + +/* + * Base class for lazily read Java heap objects. + */ +public abstract class JavaLazyReadObject extends JavaHeapObject { + + // file offset from which this object data starts + private final long offset; + + protected JavaLazyReadObject(long offset) { + this.offset = offset; + } + + @Override + public final long getSize() { + return getValueLength() + getClazz().getMinimumObjectSize(); + } + + protected final long getOffset() { + return offset; + } + + protected ReadBuffer buf() { + return getClazz().getReadBuffer(); + } + + protected int idSize() { + return getClazz().getIdentifierSize(); + } + + // return the length of the data for this object + protected final long getValueLength() { + try { + return readValueLength(); + } catch (IOException exp) { + System.err.println("lazy read failed at offset " + offset); + exp.printStackTrace(); + return 0; + } + } + + // get this object's content as byte array + protected final JavaThing[] getValue() { + try { + return readValue(); + } catch (IOException exp) { + System.err.println("lazy read failed at offset " + offset); + exp.printStackTrace(); + return Snapshot.EMPTY_JAVATHING_ARRAY; + } + } + + // get ID of this object + public final long getId() { + try { + if (idSize() == 4) { + return ((long)buf().getInt(offset)) & Snapshot.SMALL_ID_MASK; + } else { + return buf().getLong(offset); + } + } catch (IOException exp) { + System.err.println("lazy read failed at offset " + offset); + exp.printStackTrace(); + return -1; + } + } + + protected abstract long readValueLength() throws IOException; + protected abstract JavaThing[] readValue() throws IOException; + + // make Integer or Long for given object ID + protected static Number makeId(long id) { + if ((id & ~Snapshot.SMALL_ID_MASK) == 0) { + return (int)id; + } else { + return id; + } + } + + // get ID as long value from Number + protected static long getIdValue(Number num) { + long id = num.longValue(); + if (num instanceof Integer) { + id &= Snapshot.SMALL_ID_MASK; + } + return id; + } + + // read object ID from given index from given byte array + protected final long objectIdAt(long offset) throws IOException { + if (idSize() == 4) { + return ((long)intAt(offset)) & Snapshot.SMALL_ID_MASK; + } else { + return longAt(offset); + } + } + + // utility methods to read primitive types from byte array + protected byte byteAt(long offset) throws IOException { + return buf().getByte(offset); + } + + protected boolean booleanAt(long offset) throws IOException { + return byteAt(offset) == 0 ? false : true; + } + + protected char charAt(long offset) throws IOException { + return buf().getChar(offset); + } + + protected short shortAt(long offset) throws IOException { + return buf().getShort(offset); + } + + protected int intAt(long offset) throws IOException { + return buf().getInt(offset); + } + + protected long longAt(long offset) throws IOException { + return buf().getLong(offset); + } + + protected float floatAt(long offset) throws IOException { + int val = intAt(offset); + return Float.intBitsToFloat(val); + } + + protected double doubleAt(long offset) throws IOException { + long val = longAt(offset); + return Double.longBitsToDouble(val); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaLong.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaLong.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a long (i.e. a long field in an instance). + * + * @author Bill Foote + */ + + +public class JavaLong extends JavaValue { + + long value; + + public JavaLong(long value) { + this.value = value; + } + + public String toString() { + return Long.toString(value); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaObject.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,333 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.io.IOException; +import jdk.test.lib.hprof.parser.ReadBuffer; + +/** + * Represents Java instance + * + * @author Bill Foote + */ +public class JavaObject extends JavaLazyReadObject { + + private Object clazz; // Number before resolve + // JavaClass after resolve + /** + * Construct a new JavaObject. + * + * @param classID id of the class object + * @param offset The offset of field data + */ + public JavaObject(long classID, long offset) { + super(offset); + this.clazz = makeId(classID); + } + + public void resolve(Snapshot snapshot) { + if (clazz instanceof JavaClass) { + return; + } + if (clazz instanceof Number) { + long classID = getIdValue((Number)clazz); + clazz = snapshot.findThing(classID); + if (! (clazz instanceof JavaClass)) { + warn("Class " + Long.toHexString(classID) + " not found, " + + "adding fake class!"); + int length; + ReadBuffer buf = snapshot.getReadBuffer(); + int idSize = snapshot.getIdentifierSize(); + long lenOffset = getOffset() + 2*idSize + 4; + try { + length = buf.getInt(lenOffset); + } catch (IOException exp) { + throw new RuntimeException(exp); + } + clazz = snapshot.addFakeInstanceClass(classID, length); + } + } else { + throw new InternalError("should not reach here"); + } + + JavaClass cl = (JavaClass) clazz; + cl.resolve(snapshot); + + // while resolving, parse fields in verbose mode. + // but, getFields calls parseFields in non-verbose mode + // to avoid printing warnings repeatedly. + parseFields(true); + + cl.addInstance(this); + super.resolve(snapshot); + } + + /** + * Are we the same type as other? We are iff our clazz is the + * same type as other's. + */ + public boolean isSameTypeAs(JavaThing other) { + if (!(other instanceof JavaObject)) { + return false; + } + JavaObject oo = (JavaObject) other; + return getClazz().equals(oo.getClazz()); + } + + /** + * Return our JavaClass object. This may only be called after resolve. + */ + public JavaClass getClazz() { + return (JavaClass) clazz; + } + + public JavaThing[] getFields() { + // pass false to verbose mode so that dereference + // warnings are not printed. + return parseFields(false); + } + + // returns the value of field of given name + public JavaThing getField(String name) { + JavaThing[] flds = getFields(); + JavaField[] instFields = getClazz().getFieldsForInstance(); + for (int i = 0; i < instFields.length; i++) { + if (instFields[i].getName().equals(name)) { + return flds[i]; + } + } + return null; + } + + public int compareTo(JavaThing other) { + if (other instanceof JavaObject) { + JavaObject oo = (JavaObject) other; + return getClazz().getName().compareTo(oo.getClazz().getName()); + } + return super.compareTo(other); + } + + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + super.visitReferencedObjects(v); + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (flds[i] != null) { + if (v.mightExclude() + && v.exclude(getClazz().getClassForField(i), + getClazz().getFieldForInstance(i))) + { + // skip it + } else if (flds[i] instanceof JavaHeapObject) { + v.visit((JavaHeapObject) flds[i]); + } + } + } + } + + public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) { + if (ss.getWeakReferenceClass() != null) { + final int referentFieldIndex = ss.getReferentFieldIndex(); + if (ss.getWeakReferenceClass().isAssignableFrom(getClazz())) { + // + // REMIND: This introduces a dependency on the JDK + // implementation that is undesirable. + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (i != referentFieldIndex && flds[i] == other) { + return false; + } + } + return true; + } + } + return false; + } + + /** + * Describe the reference that this thing has to target. This will only + * be called if target is in the array returned by getChildrenForRootset. + */ + public String describeReferenceTo(JavaThing target, Snapshot ss) { + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (flds[i] == target) { + JavaField f = getClazz().getFieldForInstance(i); + return "field " + f.getName(); + } + } + return super.describeReferenceTo(target, ss); + } + + public String toString() { + if (getClazz().isString()) { + JavaThing value = getField("value"); + if (value instanceof JavaValueArray) { + return ((JavaValueArray)value).valueString(); + } else { + return "null"; + } + } else { + return super.toString(); + } + } + + // Internals only below this point + + /* + * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below: + * + * object ID + * stack trace serial number (int) + * class ID + * data length (int) + * byte[length] + */ + @Override + protected final long readValueLength() throws IOException { + long lengthOffset = getOffset() + 2 * idSize() + 4; + return buf().getInt(lengthOffset); + } + + @Override + protected final JavaThing[] readValue() throws IOException { + return parseFields(false); + } + + private long dataStartOffset() { + return getOffset() + idSize() + 4 + idSize() + 4; + } + + private JavaThing[] parseFields(boolean verbose) { + JavaClass cl = getClazz(); + int target = cl.getNumFieldsForInstance(); + JavaField[] fields = cl.getFields(); + JavaThing[] fieldValues = new JavaThing[target]; + Snapshot snapshot = cl.getSnapshot(); + int fieldNo = 0; + // In the dump file, the fields are stored in this order: + // fields of most derived class (immediate class) are stored + // first and then the super class and so on. In this object, + // fields are stored in the reverse ("natural") order. i.e., + // fields of most super class are stored first. + + // target variable is used to compensate for the fact that + // the dump file starts field values from the leaf working + // upwards in the inheritance hierarchy, whereas JavaObject + // starts with the top of the inheritance hierarchy and works down. + target -= fields.length; + JavaClass currClass = cl; + long offset = dataStartOffset(); + for (int i = 0; i < fieldValues.length; i++, fieldNo++) { + while (fieldNo >= fields.length) { + currClass = currClass.getSuperclass(); + fields = currClass.getFields(); + fieldNo = 0; + target -= fields.length; + } + JavaField f = fields[fieldNo]; + char sig = f.getSignature().charAt(0); + try { + switch (sig) { + case 'L': + case '[': { + long id = objectIdAt(offset); + offset += idSize(); + JavaObjectRef ref = new JavaObjectRef(id); + fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose); + break; + } + case 'Z': { + byte value = byteAt(offset); + offset++; + fieldValues[target+fieldNo] = new JavaBoolean(value != 0); + break; + } + case 'B': { + byte value = byteAt(offset); + offset++; + fieldValues[target+fieldNo] = new JavaByte(value); + break; + } + case 'S': { + short value = shortAt(offset); + offset += 2; + fieldValues[target+fieldNo] = new JavaShort(value); + break; + } + case 'C': { + char value = charAt(offset); + offset += 2; + fieldValues[target+fieldNo] = new JavaChar(value); + break; + } + case 'I': { + int value = intAt(offset); + offset += 4; + fieldValues[target+fieldNo] = new JavaInt(value); + break; + } + case 'J': { + long value = longAt(offset); + offset += 8; + fieldValues[target+fieldNo] = new JavaLong(value); + break; + } + case 'F': { + float value = floatAt(offset); + offset += 4; + fieldValues[target+fieldNo] = new JavaFloat(value); + break; + } + case 'D': { + double value = doubleAt(offset); + offset += 8; + fieldValues[target+fieldNo] = new JavaDouble(value); + break; + } + default: + throw new RuntimeException("invalid signature: " + sig); + + } + } catch (IOException exp) { + System.err.println("lazy read failed at offset " + offset); + exp.printStackTrace(); + return Snapshot.EMPTY_JAVATHING_ARRAY; + } + } + return fieldValues; + } + + private void warn(String msg) { + System.out.println("WARNING: " + msg); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaObjectArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaObjectArray.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.io.IOException; +import jdk.test.lib.hprof.parser.ReadBuffer; + +/** + * @author Bill Foote + */ +public class JavaObjectArray extends JavaLazyReadObject { + + private Object clazz; // Long before resolve, the class after resolve + + public JavaObjectArray(long classID, long offset) { + super(offset); + this.clazz = makeId(classID); + } + + public JavaClass getClazz() { + return (JavaClass) clazz; + } + + public void resolve(Snapshot snapshot) { + if (clazz instanceof JavaClass) { + return; + } + long classID = getIdValue((Number)clazz); + if (snapshot.isNewStyleArrayClass()) { + // Modern heap dumps do this + JavaThing t = snapshot.findThing(classID); + if (t instanceof JavaClass) { + clazz = (JavaClass) t; + } + } + if (!(clazz instanceof JavaClass)) { + JavaThing t = snapshot.findThing(classID); + if (t != null && t instanceof JavaClass) { + JavaClass el = (JavaClass) t; + String nm = el.getName(); + if (!nm.startsWith("[")) { + nm = "L" + el.getName() + ";"; + } + clazz = snapshot.getArrayClass(nm); + } + } + + if (!(clazz instanceof JavaClass)) { + clazz = snapshot.getOtherArrayType(); + } + ((JavaClass)clazz).addInstance(this); + super.resolve(snapshot); + } + + public JavaThing[] getValues() { + return getElements(); + } + + public JavaThing[] getElements() { + return getValue(); + } + + public int compareTo(JavaThing other) { + if (other instanceof JavaObjectArray) { + return 0; + } + return super.compareTo(other); + } + + public int getLength() { + return (int)(getValueLength() / idSize()); + } + + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + super.visitReferencedObjects(v); + JavaThing[] elements = getElements(); + for (int i = 0; i < elements.length; i++) { + if (elements[i] != null && elements[i] instanceof JavaHeapObject) { + v.visit((JavaHeapObject) elements[i]); + } + } + } + + /** + * Describe the reference that this thing has to target. This will only + * be called if target is in the array returned by getChildrenForRootset. + */ + public String describeReferenceTo(JavaThing target, Snapshot ss) { + JavaThing[] elements = getElements(); + for (int i = 0; i < elements.length; i++) { + if (elements[i] == target) { + return "Element " + i + " of " + this; + } + } + return super.describeReferenceTo(target, ss); + } + + /* + * Java object array record (HPROF_GC_OBJ_ARRAY_DUMP) + * looks as below: + * + * object ID + * stack trace serial number (int) + * array length (int) + * array class ID + * array element IDs + */ + @Override + protected final long readValueLength() throws IOException { + long offset = getOffset() + idSize() + 4; + // length of the array in elements + long len = buf().getInt(offset); + // byte length of array + return len * idSize(); + } + + private long dataStartOffset() { + return getOffset() + idSize() + 4 + 4 + idSize(); + } + + @Override + protected final JavaThing[] readValue() throws IOException { + Snapshot snapshot = getClazz().getSnapshot(); + int len = getLength(); + long offset = dataStartOffset(); + + JavaThing[] res = new JavaThing[len]; + for (int i = 0; i < len; i++) { + long id = objectIdAt(offset); + res[i] = snapshot.findThing(id); + offset += idSize(); + } + return res; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaObjectRef.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaObjectRef.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import jdk.test.lib.hprof.util.Misc; + +/** + * A forward reference to an object. This is an intermediate representation + * for a JavaThing, when we have the thing's ID, but we might not have read + * the thing yet. + * + * @author Bill Foote + */ +public class JavaObjectRef extends JavaThing { + private long id; + + public JavaObjectRef(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public boolean isHeapAllocated() { + return true; + } + + public JavaThing dereference(Snapshot snapshot, JavaField field) { + return dereference(snapshot, field, true); + } + + public JavaThing dereference(Snapshot snapshot, JavaField field, boolean verbose) { + if (field != null && !field.hasId()) { + // If this happens, we must be a field that represents an int. + // (This only happens with .bod-style files) + return new JavaLong(id); + } + if (id == 0) { + return snapshot.getNullThing(); + } + JavaThing result = snapshot.findThing(id); + if (result == null) { + if (!snapshot.getUnresolvedObjectsOK() && verbose) { + String msg = "WARNING: Failed to resolve object id " + + Misc.toHex(id); + if (field != null) { + msg += " for field " + field.getName() + + " (signature " + field.getSignature() + ")"; + } + System.out.println(msg); + // Thread.dumpStack(); + } + result = new HackJavaValue("Unresolved object " + + Misc.toHex(id), 0); + } + return result; + } + + @Override + public long getSize() { + return 0; + } + + public String toString() { + return "Unresolved object " + Misc.toHex(id); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaShort.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaShort.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a short (i.e. a short field in an instance). + * + * @author Bill Foote + */ + + +public class JavaShort extends JavaValue { + + short value; + + public JavaShort(short value) { + this.value = value; + } + + public String toString() { + return "" + value; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaStatic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaStatic.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * + * @author Bill Foote + */ + +/** + * Represents the value of a static field of a JavaClass + */ + +public class JavaStatic { + + private JavaField field; + private JavaThing value; + + public JavaStatic(JavaField field, JavaThing value) { + this.field = field; + this.value = value; + } + + public void resolve(JavaClass clazz, Snapshot snapshot) { + long id = -1; + if (value instanceof JavaObjectRef) { + id = ((JavaObjectRef)value).getId(); + } + value = value.dereference(snapshot, field); + if (value.isHeapAllocated() && + clazz.getLoader() == snapshot.getNullThing()) { + // static fields are only roots if they are in classes + // loaded by the root classloader. + JavaHeapObject ho = (JavaHeapObject) value; + String s = "Static reference from " + clazz.getName() + + "." + field.getName(); + snapshot.addRoot(new Root(id, clazz.getId(), + Root.JAVA_STATIC, s)); + } + } + + public JavaField getField() { + return field; + } + + public JavaThing getValue() { + return value; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaThing.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaThing.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.util.Enumeration; +import java.util.Hashtable; + + +/** + * + * @author Bill Foote + */ + + +/** + * Represents a java "Thing". A thing is anything that can be the value of + * a field. This includes JavaHeapObject, JavaObjectRef, and JavaValue. + */ + +public abstract class JavaThing { + + protected JavaThing() { + } + + /** + * If this is a forward reference, figure out what it really + * refers to. + * + * @param snapshot The snapshot this is for + * @param field The field this thing represents. If null, it is + * assumed this thing is an object (and never a value). + */ + public JavaThing dereference(Snapshot shapshot, JavaField field) { + return this; + } + + + /** + * Are we the same type as other? + * + * @see JavaObject.isSameTypeAs() + */ + public boolean isSameTypeAs(JavaThing other) { + return getClass() == other.getClass(); + } + /** + * @return true iff this represents a heap-allocated object + */ + abstract public boolean isHeapAllocated(); + + /** + * @return the size of this object, in bytes, including VM overhead + */ + abstract public long getSize(); + + /** + * @return a human-readable string representation of this thing + */ + abstract public String toString(); + + /** + * Compare our string representation to other's + * @see java.lang.String.compareTo() + */ + public int compareTo(JavaThing other) { + return toString().compareTo(other.toString()); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaValue.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Abstract base class for all value types (ints, longs, floats, etc.) + * + * @author Bill Foote + */ + + + + +public abstract class JavaValue extends JavaThing { + + protected JavaValue() { + } + + public boolean isHeapAllocated() { + return false; + } + + abstract public String toString(); + + @Override + public long getSize() { + // The size of a value is already accounted for in the class + // that has the data member. + return 0; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/JavaValueArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/JavaValueArray.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,354 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import jdk.test.lib.hprof.parser.ReadBuffer; +import java.io.IOException; + +/** + * An array of values, that is, an array of ints, boolean, floats or the like. + * + * @author Bill Foote + */ +public class JavaValueArray extends JavaLazyReadObject + /*imports*/ implements ArrayTypeCodes { + + private static String arrayTypeName(byte sig) { + switch (sig) { + case 'B': + return "byte[]"; + case 'Z': + return "boolean[]"; + case 'C': + return "char[]"; + case 'S': + return "short[]"; + case 'I': + return "int[]"; + case 'F': + return "float[]"; + case 'J': + return "long[]"; + case 'D': + return "double[]"; + default: + throw new RuntimeException("invalid array element sig: " + sig); + } + } + + private static int elementSize(byte type) { + switch (type) { + case T_BYTE: + case T_BOOLEAN: + return 1; + case T_CHAR: + case T_SHORT: + return 2; + case T_INT: + case T_FLOAT: + return 4; + case T_LONG: + case T_DOUBLE: + return 8; + default: + throw new RuntimeException("invalid array element type: " + type); + } + } + + /* + * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks + * as below: + * + * object ID + * stack trace serial number (int) + * number of elements (int) + * element type (byte) + * array data + */ + @Override + protected final long readValueLength() throws IOException { + long offset = getOffset() + idSize() + 4; + // length of the array in elements + long len = buf().getInt(offset); + // byte length of array + return len * elementSize(getElementType()); + } + + private long dataStartOffset() { + return getOffset() + idSize() + 4 + 4 + 1; + } + + + @Override + protected final JavaThing[] readValue() throws IOException { + int len = getLength(); + long offset = dataStartOffset(); + + JavaThing[] res = new JavaThing[len]; + synchronized (buf()) { + switch (getElementType()) { + case 'Z': { + for (int i = 0; i < len; i++) { + res[i] = new JavaBoolean(booleanAt(offset)); + offset += 1; + } + return res; + } + case 'B': { + for (int i = 0; i < len; i++) { + res[i] = new JavaByte(byteAt(offset)); + offset += 1; + } + return res; + } + case 'C': { + for (int i = 0; i < len; i++) { + res[i] = new JavaChar(charAt(offset)); + offset += 2; + } + return res; + } + case 'S': { + for (int i = 0; i < len; i++) { + res[i] = new JavaShort(shortAt(offset)); + offset += 2; + } + return res; + } + case 'I': { + for (int i = 0; i < len; i++) { + res[i] = new JavaInt(intAt(offset)); + offset += 4; + } + return res; + } + case 'J': { + for (int i = 0; i < len; i++) { + res[i] = new JavaLong(longAt(offset)); + offset += 8; + } + return res; + } + case 'F': { + for (int i = 0; i < len; i++) { + res[i] = new JavaFloat(floatAt(offset)); + offset += 4; + } + return res; + } + case 'D': { + for (int i = 0; i < len; i++) { + res[i] = new JavaDouble(doubleAt(offset)); + offset += 8; + } + return res; + } + default: { + throw new RuntimeException("unknown primitive type?"); + } + } + } + } + + // JavaClass set only after resolve. + private JavaClass clazz; + + // This field contains elementSignature byte and + // divider to be used to calculate length. Note that + // length of content byte[] is not same as array length. + // Actual array length is (byte[].length / divider) + private int data; + + // First 8 bits of data is used for element signature + private static final int SIGNATURE_MASK = 0x0FF; + + // Next 8 bits of data is used for length divider + private static final int LENGTH_DIVIDER_MASK = 0x0FF00; + + // Number of bits to shift to get length divider + private static final int LENGTH_DIVIDER_SHIFT = 8; + + public JavaValueArray(byte elementSignature, long offset) { + super(offset); + this.data = (elementSignature & SIGNATURE_MASK); + } + + public JavaClass getClazz() { + return clazz; + } + + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + super.visitReferencedObjects(v); + } + + public void resolve(Snapshot snapshot) { + if (clazz instanceof JavaClass) { + return; + } + byte elementSig = getElementType(); + clazz = snapshot.findClass(arrayTypeName(elementSig)); + if (clazz == null) { + clazz = snapshot.getArrayClass("" + ((char) elementSig)); + } + getClazz().addInstance(this); + super.resolve(snapshot); + } + + public int getLength() { + int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT; + if (divider == 0) { + byte elementSignature = getElementType(); + switch (elementSignature) { + case 'B': + case 'Z': + divider = 1; + break; + case 'C': + case 'S': + divider = 2; + break; + case 'I': + case 'F': + divider = 4; + break; + case 'J': + case 'D': + divider = 8; + break; + default: + throw new RuntimeException("unknown primitive type: " + + elementSignature); + } + data |= (divider << LENGTH_DIVIDER_SHIFT); + } + return (int)(getValueLength() / divider); + } + + public JavaThing[] getElements() { + return getValue(); + } + + public byte getElementType() { + return (byte) (data & SIGNATURE_MASK); + } + + private void checkIndex(int index) { + if (index < 0 || index >= getLength()) { + throw new ArrayIndexOutOfBoundsException(index); + } + } + + private void requireType(char type) { + if (getElementType() != type) { + throw new RuntimeException("not of type : " + type); + } + } + + public String valueString() { + return valueString(true); + } + + public String valueString(boolean bigLimit) { + // Char arrays deserve special treatment + StringBuilder result; + JavaThing[] things = getValue(); + byte elementSignature = getElementType(); + if (elementSignature == 'C') { + result = new StringBuilder(); + for (int i = 0; i < things.length; i++) { + result.append(things[i]); + } + } else { + int limit = 8; + if (bigLimit) { + limit = 1000; + } + result = new StringBuilder("{"); + for (int i = 0; i < things.length; i++) { + if (i > 0) { + result.append(", "); + } + if (i >= limit) { + result.append("... "); + break; + } + switch (elementSignature) { + case 'Z': { + boolean val = ((JavaBoolean)things[i]).value; + if (val) { + result.append("true"); + } else { + result.append("false"); + } + break; + } + case 'B': { + byte val = ((JavaByte)things[i]).value; + result.append("0x").append(Integer.toString(val, 16)); + break; + } + case 'S': { + short val = ((JavaShort)things[i]).value; + result.append(val); + break; + } + case 'I': { + int val = ((JavaInt)things[i]).value; + result.append(val); + break; + } + case 'J': { // long + long val = ((JavaLong)things[i]).value; + result.append(val); + break; + } + case 'F': { + float val = ((JavaFloat)things[i]).value; + result.append(val); + break; + } + case 'D': { // double + double val = ((JavaDouble)things[i]).value; + result.append(val); + break; + } + default: { + throw new RuntimeException("unknown primitive type?"); + } + } + } + result.append('}'); + } + return result.toString(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/ReachableExcludes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/ReachableExcludes.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + + +/** + * This represents a set of data members that should be excluded from the + * reachable objects query. This is useful to exclude observers from the + * transitive closure of objects reachable from a given object, allowing + * some kind of real determination of the "size" of that object. + * + */ + +public interface ReachableExcludes { + /** + * @return true iff the given field is on the hitlist of excluded + * fields. + */ + public boolean isExcluded(String fieldName); +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/ReachableExcludesImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/ReachableExcludesImpl.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.BufferedReader; +import java.io.IOException; + +import java.util.Hashtable; + +/** + * This represents a set of data members that should be excluded from the + * reachable objects query. + * This is useful to exclude observers from the + * transitive closure of objects reachable from a given object, allowing + * some kind of real determination of the "size" of that object. + * + * @author Bill Foote + */ +public class ReachableExcludesImpl implements ReachableExcludes { + + private File excludesFile; + private long lastModified; + private Hashtable methods; // Used as a bag + + /** + * Create a new ReachableExcludesImpl over the given file. The file will be + * re-read whenever the timestamp changes. + */ + public ReachableExcludesImpl(File excludesFile) { + this.excludesFile = excludesFile; + readFile(); + } + + private void readFileIfNeeded() { + if (excludesFile.lastModified() != lastModified) { + synchronized(this) { + if (excludesFile.lastModified() != lastModified) { + readFile(); + } + } + } + } + + private void readFile() { + long lm = excludesFile.lastModified(); + Hashtable m = new Hashtable(); + + try (BufferedReader r = new BufferedReader(new InputStreamReader( + new FileInputStream(excludesFile)))) { + String method; + while ((method = r.readLine()) != null) { + m.put(method, method); + } + lastModified = lm; + methods = m; // We want this to be atomic + } catch (IOException ex) { + System.out.println("Error reading " + excludesFile + ": " + ex); + } + } + + /** + * @return true iff the given field is on the histlist of excluded + * fields. + */ + public boolean isExcluded(String fieldName) { + readFileIfNeeded(); + return methods.get(fieldName) != null; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/ReachableObjects.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/ReachableObjects.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.util.Vector; +import java.util.Hashtable; +import java.util.Enumeration; + +import jdk.test.lib.hprof.util.ArraySorter; +import jdk.test.lib.hprof.util.Comparer; + +/** + * @author A. Sundararajan + */ + +public class ReachableObjects { + public ReachableObjects(JavaHeapObject root, + final ReachableExcludes excludes) { + this.root = root; + + final Hashtable bag = new Hashtable(); + final Hashtable fieldsExcluded = new Hashtable(); //Bag + final Hashtable fieldsUsed = new Hashtable(); // Bag + JavaHeapObjectVisitor visitor = new AbstractJavaHeapObjectVisitor() { + public void visit(JavaHeapObject t) { + // Size is zero for things like integer fields + if (t != null && t.getSize() > 0 && bag.get(t) == null) { + bag.put(t, t); + t.visitReferencedObjects(this); + } + } + + public boolean mightExclude() { + return excludes != null; + } + + public boolean exclude(JavaClass clazz, JavaField f) { + if (excludes == null) { + return false; + } + String nm = clazz.getName() + "." + f.getName(); + if (excludes.isExcluded(nm)) { + fieldsExcluded.put(nm, nm); + return true; + } else { + fieldsUsed.put(nm, nm); + return false; + } + } + }; + // Put the closure of root and all objects reachable from root into + // bag (depth first), but don't include root: + visitor.visit(root); + bag.remove(root); + + // Now grab the elements into a vector, and sort it in decreasing size + JavaThing[] things = new JavaThing[bag.size()]; + int i = 0; + for (Enumeration e = bag.elements(); e.hasMoreElements(); ) { + things[i++] = (JavaThing) e.nextElement(); + } + ArraySorter.sort(things, new Comparer() { + public int compare(Object lhs, Object rhs) { + JavaThing left = (JavaThing) lhs; + JavaThing right = (JavaThing) rhs; + long diff = right.getSize() - left.getSize(); + if (diff != 0) { + return Long.signum(diff); + } + return left.compareTo(right); + } + }); + this.reachables = things; + + this.totalSize = root.getSize(); + for (i = 0; i < things.length; i++) { + this.totalSize += things[i].getSize(); + } + + excludedFields = getElements(fieldsExcluded); + usedFields = getElements(fieldsUsed); + } + + public JavaHeapObject getRoot() { + return root; + } + + public JavaThing[] getReachables() { + return reachables; + } + + public long getTotalSize() { + return totalSize; + } + + public String[] getExcludedFields() { + return excludedFields; + } + + public String[] getUsedFields() { + return usedFields; + } + + private String[] getElements(Hashtable ht) { + Object[] keys = ht.keySet().toArray(); + int len = keys.length; + String[] res = new String[len]; + System.arraycopy(keys, 0, res, 0, len); + ArraySorter.sortArrayOfStrings(res); + return res; + } + + private JavaHeapObject root; + private JavaThing[] reachables; + private String[] excludedFields; + private String[] usedFields; + private long totalSize; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/ReferenceChain.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/ReferenceChain.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * Represents a chain of references to some target object + * + * @author Bill Foote + */ + +public class ReferenceChain { + + JavaHeapObject obj; // Object referred to + ReferenceChain next; // Next in chain + + public ReferenceChain(JavaHeapObject obj, ReferenceChain next) { + this.obj = obj; + this.next = next; + } + + public JavaHeapObject getObj() { + return obj; + } + + public ReferenceChain getNext() { + return next; + } + + public int getDepth() { + int count = 1; + ReferenceChain tmp = next; + while (tmp != null) { + count++; + tmp = tmp.next; + } + return count; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/Root.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/Root.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import jdk.test.lib.hprof.util.Misc; + +/** + * + * @author Bill Foote + */ + + +/** + * Represents a member of the rootset, that is, one of the objects that + * the GC starts from when marking reachable objects. + */ + +public class Root { + + private long id; // ID of the JavaThing we refer to + private long refererId; // Thread or Class responsible for this, or 0 + private int index = -1; // Index in Snapshot.roots + private int type; + private String description; + private JavaHeapObject referer = null; + private StackTrace stackTrace = null; + + // Values for type. Higher values are more interesting -- see getType(). + // See also getTypeName() + public final static int INVALID_TYPE = 0; + public final static int UNKNOWN = 1; + public final static int SYSTEM_CLASS = 2; + + public final static int NATIVE_LOCAL = 3; + public final static int NATIVE_STATIC = 4; + public final static int THREAD_BLOCK = 5; + public final static int BUSY_MONITOR = 6; + public final static int JAVA_LOCAL = 7; + public final static int NATIVE_STACK = 8; + public final static int JAVA_STATIC = 9; + + + public Root(long id, long refererId, int type, String description) { + this(id, refererId, type, description, null); + } + + + public Root(long id, long refererId, int type, String description, + StackTrace stackTrace) { + this.id = id; + this.refererId = refererId; + this.type = type; + this.description = description; + this.stackTrace = stackTrace; + } + + public long getId() { + return id; + } + + public String getIdString() { + return Misc.toHex(id); + } + + public String getDescription() { + if ("".equals(description)) { + return getTypeName() + " Reference"; + } else { + return description; + } + } + + /** + * Return type. We guarantee that more interesting roots will have + * a type that is numerically higher. + */ + public int getType() { + return type; + } + + public String getTypeName() { + switch(type) { + case INVALID_TYPE: return "Invalid (?!?)"; + case UNKNOWN: return "Unknown"; + case SYSTEM_CLASS: return "System Class"; + case NATIVE_LOCAL: return "JNI Local"; + case NATIVE_STATIC: return "JNI Global"; + case THREAD_BLOCK: return "Thread Block"; + case BUSY_MONITOR: return "Busy Monitor"; + case JAVA_LOCAL: return "Java Local"; + case NATIVE_STACK: return "Native Stack (possibly Java local)"; + case JAVA_STATIC: return "Java Static"; + default: return "??"; + } + } + + /** + * Given two Root instances, return the one that is most interesting. + */ + public Root mostInteresting(Root other) { + if (other.type > this.type) { + return other; + } else { + return this; + } + } + + /** + * Get the object that's responsible for this root, if there is one. + * This will be null, a Thread object, or a Class object. + */ + public JavaHeapObject getReferer() { + return referer; + } + + /** + * @return the stack trace responsible for this root, or null if there + * is none. + */ + public StackTrace getStackTrace() { + return stackTrace; + } + + /** + * @return The index of this root in Snapshot.roots + */ + public int getIndex() { + return index; + } + + void resolve(Snapshot ss) { + if (refererId != 0) { + referer = ss.findThing(refererId); + } + if (stackTrace != null) { + stackTrace.resolve(ss); + } + } + + void setIndex(int i) { + index = i; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/Snapshot.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/Snapshot.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,635 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.lang.ref.SoftReference; +import java.util.*; + +import jdk.test.lib.hprof.parser.ReadBuffer; +import jdk.test.lib.hprof.util.Misc; + +/** + * + * @author Bill Foote + */ + +/** + * Represents a snapshot of the Java objects in the VM at one instant. + * This is the top-level "model" object read out of a single .hprof or .bod + * file. + */ + +public class Snapshot implements AutoCloseable { + + public static final long SMALL_ID_MASK = 0x0FFFFFFFFL; + public static final JavaThing[] EMPTY_JAVATHING_ARRAY = new JavaThing[0]; + + private static final JavaField[] EMPTY_FIELD_ARRAY = new JavaField[0]; + private static final JavaStatic[] EMPTY_STATIC_ARRAY = new JavaStatic[0]; + + // all heap objects + private Hashtable heapObjects = + new Hashtable(); + + private Hashtable fakeClasses = + new Hashtable(); + + // all Roots in this Snapshot + private Vector roots = new Vector(); + + // name-to-class map + private Map classes = + new TreeMap(); + + // new objects relative to a baseline - lazily initialized + private volatile Map newObjects; + + // allocation site traces for all objects - lazily initialized + private volatile Map siteTraces; + + // object-to-Root map for all objects + private Map rootsMap = + new HashMap(); + + // soft cache of finalizeable objects - lazily initialized + private SoftReference> finalizablesCache; + + // represents null reference + private JavaThing nullThing; + + // java.lang.ref.Reference class + private JavaClass weakReferenceClass; + // index of 'referent' field in java.lang.ref.Reference class + private int referentFieldIndex; + + // java.lang.Class class + private JavaClass javaLangClass; + // java.lang.String class + private JavaClass javaLangString; + // java.lang.ClassLoader class + private JavaClass javaLangClassLoader; + + // unknown "other" array class + private volatile JavaClass otherArrayType; + // Stuff to exclude from reachable query + private ReachableExcludes reachableExcludes; + // the underlying heap dump buffer + private ReadBuffer readBuf; + + // True iff some heap objects have isNew set + private boolean hasNewSet; + private boolean unresolvedObjectsOK; + + // whether object array instances have new style class or + // old style (element) class. + private boolean newStyleArrayClass; + + // object id size in the heap dump + private int identifierSize = 4; + + // minimum object size - accounts for object header in + // most Java virtual machines - we assume 2 identifierSize + // (which is true for Sun's hotspot JVM). + private int minimumObjectSize; + + public Snapshot(ReadBuffer buf) { + nullThing = new HackJavaValue("", 0); + readBuf = buf; + } + + public void setSiteTrace(JavaHeapObject obj, StackTrace trace) { + if (trace != null && trace.getFrames().length != 0) { + initSiteTraces(); + siteTraces.put(obj, trace); + } + } + + public StackTrace getSiteTrace(JavaHeapObject obj) { + if (siteTraces != null) { + return siteTraces.get(obj); + } else { + return null; + } + } + + public void setNewStyleArrayClass(boolean value) { + newStyleArrayClass = value; + } + + public boolean isNewStyleArrayClass() { + return newStyleArrayClass; + } + + public void setIdentifierSize(int size) { + identifierSize = size; + minimumObjectSize = 2 * size; + } + + public int getIdentifierSize() { + return identifierSize; + } + + public int getMinimumObjectSize() { + return minimumObjectSize; + } + + public void addHeapObject(long id, JavaHeapObject ho) { + heapObjects.put(makeId(id), ho); + } + + public void addRoot(Root r) { + r.setIndex(roots.size()); + roots.addElement(r); + } + + public void addClass(long id, JavaClass c) { + addHeapObject(id, c); + putInClassesMap(c); + } + + JavaClass addFakeInstanceClass(long classID, int instSize) { + // Create a fake class name based on ID. + String name = "unknown-class<@" + Misc.toHex(classID) + ">"; + + // Create fake fields convering the given instance size. + // Create as many as int type fields and for the left over + // size create byte type fields. + int numInts = instSize / 4; + int numBytes = instSize % 4; + JavaField[] fields = new JavaField[numInts + numBytes]; + int i; + for (i = 0; i < numInts; i++) { + fields[i] = new JavaField("unknown-field-" + i, "I"); + } + for (i = 0; i < numBytes; i++) { + fields[i + numInts] = new JavaField("unknown-field-" + + i + numInts, "B"); + } + + // Create fake instance class + JavaClass c = new JavaClass(name, 0, 0, 0, 0, fields, + EMPTY_STATIC_ARRAY, instSize); + // Add the class + addFakeClass(makeId(classID), c); + return c; + } + + + /** + * @return true iff it's possible that some JavaThing instances might + * isNew set + * + * @see JavaThing.isNew() + */ + public boolean getHasNewSet() { + return hasNewSet; + } + + // + // Used in the body of resolve() + // + private static class MyVisitor extends AbstractJavaHeapObjectVisitor { + JavaHeapObject t; + public void visit(JavaHeapObject other) { + other.addReferenceFrom(t); + } + } + + // To show heap parsing progress, we print a '.' after this limit + private static final int DOT_LIMIT = 5000; + + /** + * Called after reading complete, to initialize the structure + */ + public void resolve(boolean calculateRefs) { + System.out.println("Resolving " + heapObjects.size() + " objects..."); + + // First, resolve the classes. All classes must be resolved before + // we try any objects, because the objects use classes in their + // resolution. + javaLangClass = findClass("java.lang.Class"); + if (javaLangClass == null) { + System.out.println("WARNING: hprof file does not include java.lang.Class!"); + javaLangClass = new JavaClass("java.lang.Class", 0, 0, 0, 0, + EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0); + addFakeClass(javaLangClass); + } + javaLangString = findClass("java.lang.String"); + if (javaLangString == null) { + System.out.println("WARNING: hprof file does not include java.lang.String!"); + javaLangString = new JavaClass("java.lang.String", 0, 0, 0, 0, + EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0); + addFakeClass(javaLangString); + } + javaLangClassLoader = findClass("java.lang.ClassLoader"); + if (javaLangClassLoader == null) { + System.out.println("WARNING: hprof file does not include java.lang.ClassLoader!"); + javaLangClassLoader = new JavaClass("java.lang.ClassLoader", 0, 0, 0, 0, + EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0); + addFakeClass(javaLangClassLoader); + } + + for (JavaHeapObject t : heapObjects.values()) { + if (t instanceof JavaClass) { + t.resolve(this); + } + } + + // Now, resolve everything else. + for (JavaHeapObject t : heapObjects.values()) { + if (!(t instanceof JavaClass)) { + t.resolve(this); + } + } + + heapObjects.putAll(fakeClasses); + fakeClasses.clear(); + + weakReferenceClass = findClass("java.lang.ref.Reference"); + referentFieldIndex = 0; + if (weakReferenceClass != null) { + JavaField[] fields = weakReferenceClass.getFieldsForInstance(); + for (int i = 0; i < fields.length; i++) { + if ("referent".equals(fields[i].getName())) { + referentFieldIndex = i; + break; + } + } + } + + if (calculateRefs) { + calculateReferencesToObjects(); + System.out.print("Eliminating duplicate references"); + System.out.flush(); + // This println refers to the *next* step + } + int count = 0; + for (JavaHeapObject t : heapObjects.values()) { + t.setupReferers(); + ++count; + if (calculateRefs && count % DOT_LIMIT == 0) { + System.out.print("."); + System.out.flush(); + } + } + if (calculateRefs) { + System.out.println(""); + } + + // to ensure that Iterator.remove() on getClasses() + // result will throw exception.. + classes = Collections.unmodifiableMap(classes); + } + + private void calculateReferencesToObjects() { + System.out.print("Chasing references, expect " + + (heapObjects.size() / DOT_LIMIT) + " dots"); + System.out.flush(); + int count = 0; + MyVisitor visitor = new MyVisitor(); + for (JavaHeapObject t : heapObjects.values()) { + visitor.t = t; + // call addReferenceFrom(t) on all objects t references: + t.visitReferencedObjects(visitor); + ++count; + if (count % DOT_LIMIT == 0) { + System.out.print("."); + System.out.flush(); + } + } + System.out.println(); + for (Root r : roots) { + r.resolve(this); + JavaHeapObject t = findThing(r.getId()); + if (t != null) { + t.addReferenceFromRoot(r); + } + } + } + + public void markNewRelativeTo(Snapshot baseline) { + hasNewSet = true; + for (JavaHeapObject t : heapObjects.values()) { + boolean isNew; + long thingID = t.getId(); + if (thingID == 0L || thingID == -1L) { + isNew = false; + } else { + JavaThing other = baseline.findThing(t.getId()); + if (other == null) { + isNew = true; + } else { + isNew = !t.isSameTypeAs(other); + } + } + t.setNew(isNew); + } + } + + public Enumeration getThings() { + return heapObjects.elements(); + } + + + public JavaHeapObject findThing(long id) { + Number idObj = makeId(id); + JavaHeapObject jho = heapObjects.get(idObj); + return jho != null? jho : fakeClasses.get(idObj); + } + + public JavaHeapObject findThing(String id) { + return findThing(Misc.parseHex(id)); + } + + public JavaClass findClass(String name) { + if (name.startsWith("0x")) { + return (JavaClass) findThing(name); + } else { + return classes.get(name); + } + } + + /** + * Return an Iterator of all of the classes in this snapshot. + **/ + public Iterator getClasses() { + // note that because classes is a TreeMap + // classes are already sorted by name + return classes.values().iterator(); + } + + public JavaClass[] getClassesArray() { + JavaClass[] res = new JavaClass[classes.size()]; + classes.values().toArray(res); + return res; + } + + public synchronized Enumeration getFinalizerObjects() { + Vector obj; + if (finalizablesCache != null && + (obj = finalizablesCache.get()) != null) { + return obj.elements(); + } + + JavaClass clazz = findClass("java.lang.ref.Finalizer"); + JavaObject queue = (JavaObject) clazz.getStaticField("queue"); + JavaThing tmp = queue.getField("head"); + Vector finalizables = new Vector(); + if (tmp != getNullThing()) { + JavaObject head = (JavaObject) tmp; + while (true) { + JavaHeapObject referent = (JavaHeapObject) head.getField("referent"); + JavaThing next = head.getField("next"); + if (next == getNullThing() || next.equals(head)) { + break; + } + head = (JavaObject) next; + finalizables.add(referent); + } + } + finalizablesCache = new SoftReference>(finalizables); + return finalizables.elements(); + } + + public Enumeration getRoots() { + return roots.elements(); + } + + public Root[] getRootsArray() { + Root[] res = new Root[roots.size()]; + roots.toArray(res); + return res; + } + + public Root getRootAt(int i) { + return roots.elementAt(i); + } + + public ReferenceChain[] + rootsetReferencesTo(JavaHeapObject target, boolean includeWeak) { + Vector fifo = new Vector(); // This is slow... A real fifo would help + // Must be a fifo to go breadth-first + Hashtable visited = new Hashtable(); + // Objects are added here right after being added to fifo. + Vector result = new Vector(); + visited.put(target, target); + fifo.addElement(new ReferenceChain(target, null)); + + while (fifo.size() > 0) { + ReferenceChain chain = fifo.elementAt(0); + fifo.removeElementAt(0); + JavaHeapObject curr = chain.getObj(); + if (curr.getRoot() != null) { + result.addElement(chain); + // Even though curr is in the rootset, we want to explore its + // referers, because they might be more interesting. + } + Enumeration referers = curr.getReferers(); + while (referers.hasMoreElements()) { + JavaHeapObject t = (JavaHeapObject) referers.nextElement(); + if (t != null && !visited.containsKey(t)) { + if (includeWeak || !t.refersOnlyWeaklyTo(this, curr)) { + visited.put(t, t); + fifo.addElement(new ReferenceChain(t, chain)); + } + } + } + } + + ReferenceChain[] realResult = new ReferenceChain[result.size()]; + for (int i = 0; i < result.size(); i++) { + realResult[i] = result.elementAt(i); + } + return realResult; + } + + public boolean getUnresolvedObjectsOK() { + return unresolvedObjectsOK; + } + + public void setUnresolvedObjectsOK(boolean v) { + unresolvedObjectsOK = v; + } + + public JavaClass getWeakReferenceClass() { + return weakReferenceClass; + } + + public int getReferentFieldIndex() { + return referentFieldIndex; + } + + public JavaThing getNullThing() { + return nullThing; + } + + public void setReachableExcludes(ReachableExcludes e) { + reachableExcludes = e; + } + + public ReachableExcludes getReachableExcludes() { + return reachableExcludes; + } + + // package privates + void addReferenceFromRoot(Root r, JavaHeapObject obj) { + Root root = rootsMap.get(obj); + if (root == null) { + rootsMap.put(obj, r); + } else { + rootsMap.put(obj, root.mostInteresting(r)); + } + } + + Root getRoot(JavaHeapObject obj) { + return rootsMap.get(obj); + } + + JavaClass getJavaLangClass() { + return javaLangClass; + } + + JavaClass getJavaLangString() { + return javaLangString; + } + + JavaClass getJavaLangClassLoader() { + return javaLangClassLoader; + } + + JavaClass getOtherArrayType() { + if (otherArrayType == null) { + synchronized(this) { + if (otherArrayType == null) { + addFakeClass(new JavaClass("[", 0, 0, 0, 0, + EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, + 0)); + otherArrayType = findClass("["); + } + } + } + return otherArrayType; + } + + JavaClass getArrayClass(String elementSignature) { + JavaClass clazz; + synchronized(classes) { + clazz = findClass("[" + elementSignature); + if (clazz == null) { + clazz = new JavaClass("[" + elementSignature, 0, 0, 0, 0, + EMPTY_FIELD_ARRAY, EMPTY_STATIC_ARRAY, 0); + addFakeClass(clazz); + // This is needed because the JDK only creates Class structures + // for array element types, not the arrays themselves. For + // analysis, though, we need to pretend that there's a + // JavaClass for the array type, too. + } + } + return clazz; + } + + ReadBuffer getReadBuffer() { + return readBuf; + } + + void setNew(JavaHeapObject obj, boolean isNew) { + initNewObjects(); + if (isNew) { + newObjects.put(obj, Boolean.TRUE); + } + } + + boolean isNew(JavaHeapObject obj) { + if (newObjects != null) { + return newObjects.get(obj) != null; + } else { + return false; + } + } + + // Internals only below this point + private Number makeId(long id) { + if (identifierSize == 4) { + return (int)id; + } else { + return id; + } + } + + private void putInClassesMap(JavaClass c) { + String name = c.getName(); + if (classes.containsKey(name)) { + // more than one class can have the same name + // if so, create a unique name by appending + // - and id string to it. + name += "-" + c.getIdString(); + } + classes.put(c.getName(), c); + } + + private void addFakeClass(JavaClass c) { + putInClassesMap(c); + c.resolve(this); + } + + private void addFakeClass(Number id, JavaClass c) { + fakeClasses.put(id, c); + addFakeClass(c); + } + + private synchronized void initNewObjects() { + if (newObjects == null) { + synchronized (this) { + if (newObjects == null) { + newObjects = new HashMap(); + } + } + } + } + + private synchronized void initSiteTraces() { + if (siteTraces == null) { + synchronized (this) { + if (siteTraces == null) { + siteTraces = new HashMap(); + } + } + } + } + + @Override + public void close() throws Exception { + readBuf.close(); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/StackFrame.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/StackFrame.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * + * @author Bill Foote + */ + + +/** + * Represents a stack frame. + */ + +public class StackFrame { + + // + // Values for the lineNumber data member. These are the same + // as the values used in the JDK 1.2 heap dump file. + // + public final static int LINE_NUMBER_UNKNOWN = -1; + public final static int LINE_NUMBER_COMPILED = -2; + public final static int LINE_NUMBER_NATIVE = -3; + + private String methodName; + private String methodSignature; + private String className; + private String sourceFileName; + private int lineNumber; + + public StackFrame(String methodName, String methodSignature, + String className, String sourceFileName, int lineNumber) { + this.methodName = methodName; + this.methodSignature = methodSignature; + this.className = className; + this.sourceFileName = sourceFileName; + this.lineNumber = lineNumber; + } + + public void resolve(Snapshot snapshot) { + } + + public String getMethodName() { + return methodName; + } + + public String getMethodSignature() { + return methodSignature; + } + + public String getClassName() { + return className; + } + + public String getSourceFileName() { + return sourceFileName; + } + + public String getLineNumber() { + switch(lineNumber) { + case LINE_NUMBER_UNKNOWN: + return "(unknown)"; + case LINE_NUMBER_COMPILED: + return "(compiled method)"; + case LINE_NUMBER_NATIVE: + return "(native method)"; + default: + return Integer.toString(lineNumber, 10); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/model/StackTrace.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/model/StackTrace.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +/** + * + * @author Bill Foote + */ + + +/** + * Represents a stack trace, that is, an ordered collection of stack frames. + */ + +public class StackTrace { + + private StackFrame[] frames; + + public StackTrace(StackFrame[] frames) { + this.frames = frames; + } + + /** + * @param depth. The minimum reasonable depth is 1. + * + * @return a (possibly new) StackTrace that is limited to depth. + */ + public StackTrace traceForDepth(int depth) { + if (depth >= frames.length) { + return this; + } else { + StackFrame[] f = new StackFrame[depth]; + System.arraycopy(frames, 0, f, 0, depth); + return new StackTrace(f); + } + } + + public void resolve(Snapshot snapshot) { + for (int i = 0; i < frames.length; i++) { + frames[i].resolve(snapshot); + } + } + + public StackFrame[] getFrames() { + return frames; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/FileReadBuffer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Implementation of ReadBuffer using a RandomAccessFile + * + * @author A. Sundararajan + */ +class FileReadBuffer implements ReadBuffer { + // underlying file to read + private RandomAccessFile file; + + FileReadBuffer(RandomAccessFile file) { + this.file = file; + } + + private void seek(long pos) throws IOException { + file.getChannel().position(pos); + } + + public synchronized void get(long pos, byte[] buf) throws IOException { + seek(pos); + file.read(buf); + } + + @Override + public synchronized char getChar(long pos) throws IOException { + seek(pos); + return file.readChar(); + } + + @Override + public synchronized byte getByte(long pos) throws IOException { + seek(pos); + return (byte) file.read(); + } + + @Override + public synchronized short getShort(long pos) throws IOException { + seek(pos); + return file.readShort(); + } + + @Override + public synchronized int getInt(long pos) throws IOException { + seek(pos); + return file.readInt(); + } + + @Override + public synchronized long getLong(long pos) throws IOException { + seek(pos); + return file.readLong(); + } + + @Override + public void close() throws Exception { + file.close(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/HprofReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/HprofReader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,926 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.*; +import java.util.Date; +import java.util.Hashtable; +import java.util.Map; +import jdk.test.lib.hprof.model.ArrayTypeCodes; +import jdk.test.lib.hprof.model.*; + +/** + * Object that's used to read a hprof file. + * + * @author Bill Foote + */ + +public class HprofReader extends Reader /* imports */ implements ArrayTypeCodes { + + final static int MAGIC_NUMBER = 0x4a415641; + // That's "JAVA", the first part of "JAVA PROFILE ..." + private final static String[] VERSIONS = { + " PROFILE 1.0\0", + " PROFILE 1.0.1\0", + " PROFILE 1.0.2\0", + }; + + private final static int VERSION_JDK12BETA3 = 0; + private final static int VERSION_JDK12BETA4 = 1; + private final static int VERSION_JDK6 = 2; + // These version numbers are indices into VERSIONS. The instance data + // member version is set to one of these, and it drives decisions when + // reading the file. + // + // Version 1.0.1 added HPROF_GC_PRIM_ARRAY_DUMP, which requires no + // version-sensitive parsing. + // + // Version 1.0.1 changed the type of a constant pool entry from a signature + // to a typecode. + // + // Version 1.0.2 added HPROF_HEAP_DUMP_SEGMENT and HPROF_HEAP_DUMP_END + // to allow a large heap to be dumped as a sequence of heap dump segments. + // + // The HPROF agent in J2SE 1.2 through to 5.0 generate a version 1.0.1 + // file. In Java SE 6.0 the version is either 1.0.1 or 1.0.2 depending on + // the size of the heap (normally it will be 1.0.1 but for multi-GB + // heaps the heap dump will not fit in a HPROF_HEAP_DUMP record so the + // dump is generated as version 1.0.2). + + // + // Record types: + // + static final int HPROF_UTF8 = 0x01; + static final int HPROF_LOAD_CLASS = 0x02; + static final int HPROF_UNLOAD_CLASS = 0x03; + static final int HPROF_FRAME = 0x04; + static final int HPROF_TRACE = 0x05; + static final int HPROF_ALLOC_SITES = 0x06; + static final int HPROF_HEAP_SUMMARY = 0x07; + + static final int HPROF_START_THREAD = 0x0a; + static final int HPROF_END_THREAD = 0x0b; + + static final int HPROF_HEAP_DUMP = 0x0c; + + static final int HPROF_CPU_SAMPLES = 0x0d; + static final int HPROF_CONTROL_SETTINGS = 0x0e; + static final int HPROF_LOCKSTATS_WAIT_TIME = 0x10; + static final int HPROF_LOCKSTATS_HOLD_TIME = 0x11; + + static final int HPROF_GC_ROOT_UNKNOWN = 0xff; + static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01; + static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02; + static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03; + static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04; + static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05; + static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06; + static final int HPROF_GC_ROOT_MONITOR_USED = 0x07; + static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08; + + static final int HPROF_GC_CLASS_DUMP = 0x20; + static final int HPROF_GC_INSTANCE_DUMP = 0x21; + static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22; + static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23; + + static final int HPROF_HEAP_DUMP_SEGMENT = 0x1c; + static final int HPROF_HEAP_DUMP_END = 0x2c; + + private final static int T_CLASS = 2; + + private int version; // The version of .hprof being read + + private int debugLevel; + private long currPos; // Current position in the file + + private int dumpsToSkip; + private boolean callStack; // If true, read the call stack of objects + + private int identifierSize; // Size, in bytes, of identifiers. + private Hashtable names; + + // Hashtable, used to map the thread sequence number + // (aka "serial number") to the thread object ID for + // HPROF_GC_ROOT_THREAD_OBJ. ThreadObject is a trivial inner class, + // at the end of this file. + private Hashtable threadObjects; + + // Hashtable, maps class object ID to class name + // (with / converted to .) + private Hashtable classNameFromObjectID; + + // Hashtable, maps class serial # to class object ID + private Hashtable classNameFromSerialNo; + + // Hashtable maps stack frame ID to StackFrame. + // Null if we're not tracking them. + private Hashtable stackFrames; + + // Hashtable maps stack frame ID to StackTrace + // Null if we're not tracking them. + private Hashtable stackTraces; + + private Snapshot snapshot; + + public static boolean verifyMagicNumber(int numberRead) { + return (numberRead == MAGIC_NUMBER); + } + + public HprofReader(String fileName, PositionDataInputStream in, + int dumpNumber, boolean callStack, int debugLevel) + throws IOException { + super(in); + RandomAccessFile file = new RandomAccessFile(fileName, "r"); + this.snapshot = new Snapshot(MappedReadBuffer.create(file)); + this.dumpsToSkip = dumpNumber - 1; + this.callStack = callStack; + this.debugLevel = debugLevel; + names = new Hashtable(); + threadObjects = new Hashtable(43); + classNameFromObjectID = new Hashtable(); + if (callStack) { + stackFrames = new Hashtable(43); + stackTraces = new Hashtable(43); + classNameFromSerialNo = new Hashtable(); + } + } + + public Snapshot read() throws IOException { + currPos = 4; // 4 because of the magic number + version = readVersionHeader(); + identifierSize = in.readInt(); + snapshot.setIdentifierSize(identifierSize); + if (version >= VERSION_JDK12BETA4) { + snapshot.setNewStyleArrayClass(true); + } else { + snapshot.setNewStyleArrayClass(false); + } + + currPos += 4; + if (identifierSize != 4 && identifierSize != 8) { + throw new IOException("I'm sorry, but I can't deal with an identifier size of " + identifierSize + ". I can only deal with 4 or 8."); + } + System.out.println("Dump file created " + (new Date(in.readLong()))); + currPos += 8; + + for (;;) { + int type; + try { + type = in.readUnsignedByte(); + } catch (EOFException ignored) { + break; + } + in.readInt(); // Timestamp of this record + // Length of record: readInt() will return negative value for record + // length >2GB. so store 32bit value in long to keep it unsigned. + long length = in.readInt() & 0xffffffffL; + if (debugLevel > 0) { + System.out.println("Read record type " + type + + ", length " + length + + " at position " + toHex(currPos)); + } + if (length < 0) { + throw new IOException("Bad record length of " + length + + " at byte " + toHex(currPos+5) + + " of file."); + } + currPos += 9 + length; + switch (type) { + case HPROF_UTF8: { + long id = readID(); + byte[] chars = new byte[(int)length - identifierSize]; + in.readFully(chars); + names.put(id, new String(chars)); + break; + } + case HPROF_LOAD_CLASS: { + int serialNo = in.readInt(); // Not used + long classID = readID(); + int stackTraceSerialNo = in.readInt(); + long classNameID = readID(); + Long classIdI = classID; + String nm = getNameFromID(classNameID).replace('/', '.'); + classNameFromObjectID.put(classIdI, nm); + if (classNameFromSerialNo != null) { + classNameFromSerialNo.put(serialNo, nm); + } + break; + } + + case HPROF_HEAP_DUMP: { + if (dumpsToSkip <= 0) { + try { + readHeapDump(length, currPos); + } catch (EOFException exp) { + handleEOF(exp, snapshot); + } + if (debugLevel > 0) { + System.out.println(" Finished processing instances in heap dump."); + } + return snapshot; + } else { + dumpsToSkip--; + skipBytes(length); + } + break; + } + + case HPROF_HEAP_DUMP_END: { + if (version >= VERSION_JDK6) { + if (dumpsToSkip <= 0) { + skipBytes(length); // should be no-op + return snapshot; + } else { + // skip this dump (of the end record for a sequence of dump segments) + dumpsToSkip--; + } + } else { + // HPROF_HEAP_DUMP_END only recognized in >= 1.0.2 + warn("Ignoring unrecognized record type " + type); + } + skipBytes(length); // should be no-op + break; + } + + case HPROF_HEAP_DUMP_SEGMENT: { + if (version >= VERSION_JDK6) { + if (dumpsToSkip <= 0) { + try { + // read the dump segment + readHeapDump(length, currPos); + } catch (EOFException exp) { + handleEOF(exp, snapshot); + } + } else { + // all segments comprising the heap dump will be skipped + skipBytes(length); + } + } else { + // HPROF_HEAP_DUMP_SEGMENT only recognized in >= 1.0.2 + warn("Ignoring unrecognized record type " + type); + skipBytes(length); + } + break; + } + + case HPROF_FRAME: { + if (stackFrames == null) { + skipBytes(length); + } else { + long id = readID(); + String methodName = getNameFromID(readID()); + String methodSig = getNameFromID(readID()); + String sourceFile = getNameFromID(readID()); + int classSer = in.readInt(); + String className = classNameFromSerialNo.get(classSer); + int lineNumber = in.readInt(); + if (lineNumber < StackFrame.LINE_NUMBER_NATIVE) { + warn("Weird stack frame line number: " + lineNumber); + lineNumber = StackFrame.LINE_NUMBER_UNKNOWN; + } + stackFrames.put(id, + new StackFrame(methodName, methodSig, + className, sourceFile, + lineNumber)); + } + break; + } + case HPROF_TRACE: { + if (stackTraces == null) { + skipBytes(length); + } else { + int serialNo = in.readInt(); + int threadSeq = in.readInt(); // Not used + StackFrame[] frames = new StackFrame[in.readInt()]; + for (int i = 0; i < frames.length; i++) { + long fid = readID(); + frames[i] = stackFrames.get(fid); + if (frames[i] == null) { + throw new IOException("Stack frame " + toHex(fid) + " not found"); + } + } + stackTraces.put(serialNo, + new StackTrace(frames)); + } + break; + } + case HPROF_UNLOAD_CLASS: + case HPROF_ALLOC_SITES: + case HPROF_START_THREAD: + case HPROF_END_THREAD: + case HPROF_HEAP_SUMMARY: + case HPROF_CPU_SAMPLES: + case HPROF_CONTROL_SETTINGS: + case HPROF_LOCKSTATS_WAIT_TIME: + case HPROF_LOCKSTATS_HOLD_TIME: + { + // Ignore these record types + skipBytes(length); + break; + } + default: { + skipBytes(length); + warn("Ignoring unrecognized record type " + type); + } + } + } + + return snapshot; + } + + public String printStackTraces() { + StringBuffer output = new StringBuffer(); + for (Map.Entry entry : stackTraces.entrySet()) { + StackFrame[] frames = entry.getValue().getFrames(); + output.append("SerialNo " + entry.getKey() + "\n"); + for (int i = 0; i < frames.length; i++) { + output.append(" " + frames[i].getClassName() + "." + frames[i].getMethodName() + + frames[i].getMethodSignature() + " (" + frames[i].getSourceFileName() + + ":" + frames[i].getLineNumber() + ")" + "\n"); + } + } + + System.out.println(output); + return output.toString(); + } + + private void skipBytes(long length) throws IOException { + while (length > 0) { + long skipped = in.skip(length); + if (skipped == 0) { + // EOF or other problem, throw exception + throw new EOFException("Couldn't skip enough bytes"); + } + length -= skipped; + } + } + + private int readVersionHeader() throws IOException { + int candidatesLeft = VERSIONS.length; + boolean[] matched = new boolean[VERSIONS.length]; + for (int i = 0; i < candidatesLeft; i++) { + matched[i] = true; + } + + int pos = 0; + while (candidatesLeft > 0) { + char c = (char) in.readByte(); + currPos++; + for (int i = 0; i < VERSIONS.length; i++) { + if (matched[i]) { + if (c != VERSIONS[i].charAt(pos)) { // Not matched + matched[i] = false; + --candidatesLeft; + } else if (pos == VERSIONS[i].length() - 1) { // Full match + return i; + } + } + } + ++pos; + } + throw new IOException("Version string not recognized at byte " + (pos+3)); + } + + private void readHeapDump(long bytesLeft, long posAtEnd) throws IOException { + while (bytesLeft > 0) { + int type = in.readUnsignedByte(); + if (debugLevel > 0) { + System.out.println(" Read heap sub-record type " + type + + " at position " + + toHex(posAtEnd - bytesLeft)); + } + bytesLeft--; + switch(type) { + case HPROF_GC_ROOT_UNKNOWN: { + long id = readID(); + bytesLeft -= identifierSize; + snapshot.addRoot(new Root(id, 0, Root.UNKNOWN, "")); + break; + } + case HPROF_GC_ROOT_THREAD_OBJ: { + long id = readID(); + int threadSeq = in.readInt(); + int stackSeq = in.readInt(); + bytesLeft -= identifierSize + 8; + threadObjects.put(threadSeq, + new ThreadObject(id, stackSeq)); + break; + } + case HPROF_GC_ROOT_JNI_GLOBAL: { + long id = readID(); + long globalRefId = readID(); // Ignored, for now + bytesLeft -= 2*identifierSize; + snapshot.addRoot(new Root(id, 0, Root.NATIVE_STATIC, "")); + break; + } + case HPROF_GC_ROOT_JNI_LOCAL: { + long id = readID(); + int threadSeq = in.readInt(); + int depth = in.readInt(); + bytesLeft -= identifierSize + 8; + ThreadObject to = getThreadObjectFromSequence(threadSeq); + StackTrace st = getStackTraceFromSerial(to.stackSeq); + if (st != null) { + st = st.traceForDepth(depth+1); + } + snapshot.addRoot(new Root(id, to.threadId, + Root.NATIVE_LOCAL, "", st)); + break; + } + case HPROF_GC_ROOT_JAVA_FRAME: { + long id = readID(); + int threadSeq = in.readInt(); + int depth = in.readInt(); + bytesLeft -= identifierSize + 8; + ThreadObject to = getThreadObjectFromSequence(threadSeq); + StackTrace st = getStackTraceFromSerial(to.stackSeq); + if (st != null) { + st = st.traceForDepth(depth+1); + } + snapshot.addRoot(new Root(id, to.threadId, + Root.JAVA_LOCAL, "", st)); + break; + } + case HPROF_GC_ROOT_NATIVE_STACK: { + long id = readID(); + int threadSeq = in.readInt(); + bytesLeft -= identifierSize + 4; + ThreadObject to = getThreadObjectFromSequence(threadSeq); + StackTrace st = getStackTraceFromSerial(to.stackSeq); + snapshot.addRoot(new Root(id, to.threadId, + Root.NATIVE_STACK, "", st)); + break; + } + case HPROF_GC_ROOT_STICKY_CLASS: { + long id = readID(); + bytesLeft -= identifierSize; + snapshot.addRoot(new Root(id, 0, Root.SYSTEM_CLASS, "")); + break; + } + case HPROF_GC_ROOT_THREAD_BLOCK: { + long id = readID(); + int threadSeq = in.readInt(); + bytesLeft -= identifierSize + 4; + ThreadObject to = getThreadObjectFromSequence(threadSeq); + StackTrace st = getStackTraceFromSerial(to.stackSeq); + snapshot.addRoot(new Root(id, to.threadId, + Root.THREAD_BLOCK, "", st)); + break; + } + case HPROF_GC_ROOT_MONITOR_USED: { + long id = readID(); + bytesLeft -= identifierSize; + snapshot.addRoot(new Root(id, 0, Root.BUSY_MONITOR, "")); + break; + } + case HPROF_GC_CLASS_DUMP: { + int bytesRead = readClass(); + bytesLeft -= bytesRead; + break; + } + case HPROF_GC_INSTANCE_DUMP: { + int bytesRead = readInstance(); + bytesLeft -= bytesRead; + break; + } + case HPROF_GC_OBJ_ARRAY_DUMP: { + long bytesRead = readArray(false); + bytesLeft -= bytesRead; + break; + } + case HPROF_GC_PRIM_ARRAY_DUMP: { + long bytesRead = readArray(true); + bytesLeft -= bytesRead; + break; + } + default: { + throw new IOException("Unrecognized heap dump sub-record type: " + type); + } + } + } + if (bytesLeft != 0) { + warn("Error reading heap dump or heap dump segment: Byte count is " + bytesLeft + " instead of 0"); + skipBytes(bytesLeft); + } + if (debugLevel > 0) { + System.out.println(" Finished heap sub-records."); + } + } + + private long readID() throws IOException { + return (identifierSize == 4)? + (Snapshot.SMALL_ID_MASK & (long)in.readInt()) : in.readLong(); + } + + // + // Read a java value. If result is non-null, it's expected to be an + // array of one element. We use it to fake multiple return values. + // @returns the number of bytes read + // + private int readValue(JavaThing[] resultArr) throws IOException { + byte type = in.readByte(); + return 1 + readValueForType(type, resultArr); + } + + private int readValueForType(byte type, JavaThing[] resultArr) + throws IOException { + if (version >= VERSION_JDK12BETA4) { + type = signatureFromTypeId(type); + } + return readValueForTypeSignature(type, resultArr); + } + + private int readValueForTypeSignature(byte type, JavaThing[] resultArr) + throws IOException { + switch (type) { + case '[': + case 'L': { + long id = readID(); + if (resultArr != null) { + resultArr[0] = new JavaObjectRef(id); + } + return identifierSize; + } + case 'Z': { + int b = in.readByte(); + if (b != 0 && b != 1) { + warn("Illegal boolean value read"); + } + if (resultArr != null) { + resultArr[0] = new JavaBoolean(b != 0); + } + return 1; + } + case 'B': { + byte b = in.readByte(); + if (resultArr != null) { + resultArr[0] = new JavaByte(b); + } + return 1; + } + case 'S': { + short s = in.readShort(); + if (resultArr != null) { + resultArr[0] = new JavaShort(s); + } + return 2; + } + case 'C': { + char ch = in.readChar(); + if (resultArr != null) { + resultArr[0] = new JavaChar(ch); + } + return 2; + } + case 'I': { + int val = in.readInt(); + if (resultArr != null) { + resultArr[0] = new JavaInt(val); + } + return 4; + } + case 'J': { + long val = in.readLong(); + if (resultArr != null) { + resultArr[0] = new JavaLong(val); + } + return 8; + } + case 'F': { + float val = in.readFloat(); + if (resultArr != null) { + resultArr[0] = new JavaFloat(val); + } + return 4; + } + case 'D': { + double val = in.readDouble(); + if (resultArr != null) { + resultArr[0] = new JavaDouble(val); + } + return 8; + } + default: { + throw new IOException("Bad value signature: " + type); + } + } + } + + private ThreadObject getThreadObjectFromSequence(int threadSeq) + throws IOException { + ThreadObject to = threadObjects.get(threadSeq); + if (to == null) { + throw new IOException("Thread " + threadSeq + + " not found for JNI local ref"); + } + return to; + } + + private String getNameFromID(long id) throws IOException { + return getNameFromID(Long.valueOf(id)); + } + + private String getNameFromID(Long id) throws IOException { + if (id.longValue() == 0L) { + return ""; + } + String result = names.get(id); + if (result == null) { + warn("Name not found at " + toHex(id.longValue())); + return "unresolved name " + toHex(id.longValue()); + } + return result; + } + + private StackTrace getStackTraceFromSerial(int ser) throws IOException { + if (stackTraces == null) { + return null; + } + StackTrace result = stackTraces.get(ser); + if (result == null) { + warn("Stack trace not found for serial # " + ser); + } + return result; + } + + // + // Handle a HPROF_GC_CLASS_DUMP + // Return number of bytes read + // + private int readClass() throws IOException { + long id = readID(); + StackTrace stackTrace = getStackTraceFromSerial(in.readInt()); + long superId = readID(); + long classLoaderId = readID(); + long signersId = readID(); + long protDomainId = readID(); + long reserved1 = readID(); + long reserved2 = readID(); + int instanceSize = in.readInt(); + int bytesRead = 7 * identifierSize + 8; + + int numConstPoolEntries = in.readUnsignedShort(); + bytesRead += 2; + for (int i = 0; i < numConstPoolEntries; i++) { + int index = in.readUnsignedShort(); // unused + bytesRead += 2; + bytesRead += readValue(null); // We ignore the values + } + + int numStatics = in.readUnsignedShort(); + bytesRead += 2; + JavaThing[] valueBin = new JavaThing[1]; + JavaStatic[] statics = new JavaStatic[numStatics]; + for (int i = 0; i < numStatics; i++) { + long nameId = readID(); + bytesRead += identifierSize; + byte type = in.readByte(); + bytesRead++; + bytesRead += readValueForType(type, valueBin); + String fieldName = getNameFromID(nameId); + if (version >= VERSION_JDK12BETA4) { + type = signatureFromTypeId(type); + } + String signature = "" + ((char) type); + JavaField f = new JavaField(fieldName, signature); + statics[i] = new JavaStatic(f, valueBin[0]); + } + + int numFields = in.readUnsignedShort(); + bytesRead += 2; + JavaField[] fields = new JavaField[numFields]; + for (int i = 0; i < numFields; i++) { + long nameId = readID(); + bytesRead += identifierSize; + byte type = in.readByte(); + bytesRead++; + String fieldName = getNameFromID(nameId); + if (version >= VERSION_JDK12BETA4) { + type = signatureFromTypeId(type); + } + String signature = "" + ((char) type); + fields[i] = new JavaField(fieldName, signature); + } + String name = classNameFromObjectID.get(id); + if (name == null) { + warn("Class name not found for " + toHex(id)); + name = "unknown-name@" + toHex(id); + } + JavaClass c = new JavaClass(id, name, superId, classLoaderId, signersId, + protDomainId, fields, statics, + instanceSize); + snapshot.addClass(id, c); + snapshot.setSiteTrace(c, stackTrace); + + return bytesRead; + } + + private String toHex(long addr) { + return jdk.test.lib.hprof.util.Misc.toHex(addr); + } + + // + // Handle a HPROF_GC_INSTANCE_DUMP + // Return number of bytes read + // + private int readInstance() throws IOException { + long start = in.position(); + long id = readID(); + StackTrace stackTrace = getStackTraceFromSerial(in.readInt()); + long classID = readID(); + JavaClass searchedClass = snapshot.findClass( + "0x" + Long.toHexString(classID)); + if (searchedClass == null) { + throw new IOException( + "Class Record for 0x" + Long.toHexString(classID) + " not found"); + } + int bytesFollowing = in.readInt(); + int bytesRead = (2 * identifierSize) + 8 + bytesFollowing; + JavaObject jobj = new JavaObject(classID, start); + skipBytes(bytesFollowing); + snapshot.addHeapObject(id, jobj); + snapshot.setSiteTrace(jobj, stackTrace); + return bytesRead; + } + + // + // Handle a HPROF_GC_OBJ_ARRAY_DUMP or HPROF_GC_PRIM_ARRAY_DUMP + // Return number of bytes read + // + private long readArray(boolean isPrimitive) throws IOException { + long start = in.position(); + long id = readID(); + StackTrace stackTrace = getStackTraceFromSerial(in.readInt()); + int num = in.readInt(); + long bytesRead = identifierSize + 8; + long elementClassID; + if (isPrimitive) { + elementClassID = in.readByte(); + bytesRead++; + } else { + elementClassID = readID(); + bytesRead += identifierSize; + } + + // Check for primitive arrays: + byte primitiveSignature = 0x00; + int elSize = 0; + if (isPrimitive || version < VERSION_JDK12BETA4) { + switch ((int)elementClassID) { + case T_BOOLEAN: { + primitiveSignature = (byte) 'Z'; + elSize = 1; + break; + } + case T_CHAR: { + primitiveSignature = (byte) 'C'; + elSize = 2; + break; + } + case T_FLOAT: { + primitiveSignature = (byte) 'F'; + elSize = 4; + break; + } + case T_DOUBLE: { + primitiveSignature = (byte) 'D'; + elSize = 8; + break; + } + case T_BYTE: { + primitiveSignature = (byte) 'B'; + elSize = 1; + break; + } + case T_SHORT: { + primitiveSignature = (byte) 'S'; + elSize = 2; + break; + } + case T_INT: { + primitiveSignature = (byte) 'I'; + elSize = 4; + break; + } + case T_LONG: { + primitiveSignature = (byte) 'J'; + elSize = 8; + break; + } + } + if (version >= VERSION_JDK12BETA4 && primitiveSignature == 0x00) { + throw new IOException("Unrecognized typecode: " + + elementClassID); + } + } + if (primitiveSignature != 0x00) { + long size = elSize * (long)num; + bytesRead += size; + JavaValueArray va = new JavaValueArray(primitiveSignature, start); + skipBytes(size); + snapshot.addHeapObject(id, va); + snapshot.setSiteTrace(va, stackTrace); + } else { + long sz = (long)num * identifierSize; + bytesRead += sz; + JavaObjectArray arr = new JavaObjectArray(elementClassID, start); + skipBytes(sz); + snapshot.addHeapObject(id, arr); + snapshot.setSiteTrace(arr, stackTrace); + } + return bytesRead; + } + + private byte signatureFromTypeId(byte typeId) throws IOException { + switch (typeId) { + case T_CLASS: { + return (byte) 'L'; + } + case T_BOOLEAN: { + return (byte) 'Z'; + } + case T_CHAR: { + return (byte) 'C'; + } + case T_FLOAT: { + return (byte) 'F'; + } + case T_DOUBLE: { + return (byte) 'D'; + } + case T_BYTE: { + return (byte) 'B'; + } + case T_SHORT: { + return (byte) 'S'; + } + case T_INT: { + return (byte) 'I'; + } + case T_LONG: { + return (byte) 'J'; + } + default: { + throw new IOException("Invalid type id of " + typeId); + } + } + } + + private void handleEOF(EOFException exp, Snapshot snapshot) { + if (debugLevel > 0) { + exp.printStackTrace(); + } + warn("Unexpected EOF. Will miss information..."); + // we have EOF, we have to tolerate missing references + snapshot.setUnresolvedObjectsOK(true); + } + + private void warn(String msg) { + System.out.println("WARNING: " + msg); + } + + // + // A trivial data-holder class for HPROF_GC_ROOT_THREAD_OBJ. + // + private class ThreadObject { + + long threadId; + int stackSeq; + + ThreadObject(long threadId, int stackSeq) { + this.threadId = threadId; + this.stackSeq = stackSeq; + } + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/MappedReadBuffer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,136 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; + +/** + * Implementation of ReadBuffer using mapped file buffer + * + * @author A. Sundararajan + */ +class MappedReadBuffer implements ReadBuffer { + private MappedByteBuffer buf; + private RandomAccessFile file; + + MappedReadBuffer(RandomAccessFile file, MappedByteBuffer buf) { + this.file = file; + this.buf = buf; + } + + /** + * Factory method to create correct ReadBuffer for a given file. + * + * The initial purpose of this method was to choose how to read hprof file for parsing + * depending on the size of the file and the system property 'jhat.disableFileMap': + * "If file size is more than 2 GB and when file mapping is configured (default), + * use mapped file reader". + * + * However, it has been discovered a problem with this approach. + * Creating java.nio.MappedByteBuffer from inside the test leads to hprof file + * is locked on Windows until test process dies since there is no good way to + * release this resource. + * + * java.nio.MappedByteBuffer will be used only if 'jhat.enableFileMap' is set to true. + * Per default 'jhat.enableFileMap' is not set. + */ + static ReadBuffer create(RandomAccessFile file) throws IOException { + if (canUseFileMap()) { + MappedByteBuffer buf; + try { + FileChannel ch = file.getChannel(); + long size = ch.size(); + buf = ch.map(FileChannel.MapMode.READ_ONLY, 0, size); + ch.close(); + return new MappedReadBuffer(file, buf); + } catch (IOException exp) { + exp.printStackTrace(); + System.err.println("File mapping failed, will use direct read"); + // fall through + } + } // else fall through + return new FileReadBuffer(file); + } + + /** + * Set system property 'jhat.enableFileMap' to 'true' to enable file mapping. + */ + private static boolean canUseFileMap() { + String prop = System.getProperty("jhat.enableFileMap"); + return prop != null && prop.equals("true"); + } + + private void seek(long pos) throws IOException { + assert pos <= Integer.MAX_VALUE : "position overflow"; + buf.position((int)pos); + } + + @Override + public synchronized char getChar(long pos) throws IOException { + seek(pos); + return buf.getChar(); + } + + @Override + public synchronized byte getByte(long pos) throws IOException { + seek(pos); + return buf.get(); + } + + @Override + public synchronized short getShort(long pos) throws IOException { + seek(pos); + return buf.getShort(); + } + + @Override + public synchronized int getInt(long pos) throws IOException { + seek(pos); + return buf.getInt(); + } + + @Override + public synchronized long getLong(long pos) throws IOException { + seek(pos); + return buf.getLong(); + } + + @Override + public void close() throws Exception { + file.close(); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/PositionDataInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/PositionDataInputStream.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.DataInputStream; +import java.io.InputStream; + +/** + * A DataInputStream that keeps track of total bytes read + * (in effect 'position' in stream) so far. + * + */ +public class PositionDataInputStream extends DataInputStream { + public PositionDataInputStream(InputStream in) { + super(in instanceof PositionInputStream? + in : new PositionInputStream(in)); + } + + public boolean markSupported() { + return false; + } + + public void mark(int readLimit) { + throw new UnsupportedOperationException("mark"); + } + + public void reset() { + throw new UnsupportedOperationException("reset"); + } + + public long position() { + return ((PositionInputStream)in).position(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/PositionInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/PositionInputStream.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * InputStream that keeps track of total bytes read (in effect + * 'position' in stream) from the input stream. + * + */ +public class PositionInputStream extends FilterInputStream { + private long position = 0L; + + public PositionInputStream(InputStream in) { + super(in); + } + + public int read() throws IOException { + int res = super.read(); + if (res != -1) position++; + return res; + } + + public int read(byte[] b, int off, int len) throws IOException { + int res = super.read(b, off, len); + if (res != -1) position += res; + return res; + } + + public long skip(long n) throws IOException { + long res = super.skip(n); + position += res; + return res; + } + + public boolean markSupported() { + return false; + } + + public void mark(int readLimit) { + throw new UnsupportedOperationException("mark"); + } + + public void reset() { + throw new UnsupportedOperationException("reset"); + } + + public long position() { + return position; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/ReadBuffer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.IOException; + +/** + * Positionable read only buffer + * + * @author A. Sundararajan + */ +public interface ReadBuffer extends AutoCloseable { + public char getChar(long pos) throws IOException; + public byte getByte(long pos) throws IOException; + public short getShort(long pos) throws IOException; + public int getInt(long pos) throws IOException; + public long getLong(long pos) throws IOException; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/parser/Reader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/parser/Reader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.parser; + +import java.io.*; +import jdk.test.lib.hprof.model.*; + +/** + * Abstract base class for reading object dump files. A reader need not be + * thread-safe. + * + * @author Bill Foote + */ + + +public abstract class Reader { + protected PositionDataInputStream in; + + protected Reader(PositionDataInputStream in) { + this.in = in; + } + + /** + * Read a snapshot from a data input stream. It is assumed that the magic + * number has already been read. + */ + abstract public Snapshot read() throws IOException; + + /** + * Read a snapshot from a file. + * + * @param heapFile The name of a file containing a heap dump + * @param callStack If true, read the call stack of allocaation sites + */ + public static Snapshot readFile(String heapFile, boolean callStack, + int debugLevel) + throws IOException { + int dumpNumber = 1; + int pos = heapFile.lastIndexOf('#'); + if (pos > -1) { + String num = heapFile.substring(pos+1, heapFile.length()); + try { + dumpNumber = Integer.parseInt(num, 10); + } catch (java.lang.NumberFormatException ex) { + String msg = "In file name \"" + heapFile + + "\", a dump number was " + + "expected after the :, but \"" + + num + "\" was found instead."; + System.err.println(msg); + throw new IOException(msg); + } + heapFile = heapFile.substring(0, pos); + } + try (PositionDataInputStream in = new PositionDataInputStream( + new BufferedInputStream(new FileInputStream(heapFile)))) { + int i = in.readInt(); + if (i == HprofReader.MAGIC_NUMBER) { + Reader r + = new HprofReader(heapFile, in, dumpNumber, + callStack, debugLevel); + return r.read(); + } else { + throw new IOException("Unrecognized magic number: " + i); + } + } + } + + /** + * Get Stack Traces from a Hprof file. + * + * @param heapFile The name of a file containing a heap dump + */ + public static String getStack(String heapFile, int debugLevel) + throws IOException { + int dumpNumber = 1; + int pos = heapFile.lastIndexOf('#'); + if (pos > -1) { + String num = heapFile.substring(pos+1, heapFile.length()); + try { + dumpNumber = Integer.parseInt(num, 10); + } catch (java.lang.NumberFormatException ex) { + String msg = "In file name \"" + heapFile + + "\", a dump number was " + + "expected after the :, but \"" + + num + "\" was found instead."; + System.err.println(msg); + throw new IOException(msg); + } + heapFile = heapFile.substring(0, pos); + } + try (PositionDataInputStream in = new PositionDataInputStream( + new BufferedInputStream(new FileInputStream(heapFile)))) { + int i = in.readInt(); + if (i == HprofReader.MAGIC_NUMBER) { + HprofReader r + = new HprofReader(heapFile, in, dumpNumber, + true, debugLevel); + r.read(); + return r.printStackTraces(); + } else { + throw new IOException("Unrecognized magic number: " + i); + } + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/util/ArraySorter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/util/ArraySorter.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.util; +import java.util.*; + +/** + * A singleton utility class that sorts an array of objects. + *

+ * Use: + *

+ *
+ *  Stuff[] arr = ...;
+ *  ArraySorter.sort(arr, new Comparer() {
+ *      public int compare(Object lhs, Object rhs) {
+ *          return ((String) lhs).compareTo((String) rhs);
+ *      }
+ *  });
+ * 
+ * + * @author Bill Foote + */ + +public class ArraySorter { + + /** + * Sort the given array, using c for comparison + **/ + static public void sort(Object[] arr, Comparer c) { + quickSort(arr, c, 0, arr.length-1); + } + + + /** + * Sort an array of strings, using String.compareTo() + **/ + static public void sortArrayOfStrings(Object[] arr) { + sort(arr, new Comparer() { + public int compare(Object lhs, Object rhs) { + return ((String) lhs).compareTo((String) rhs); + } + }); + } + + + static private void swap(Object[] arr, int a, int b) { + Object tmp = arr[a]; + arr[a] = arr[b]; + arr[b] = tmp; + } + + // + // Sorts arr between from and to, inclusive. This is a quick, off-the-top- + // of-my-head quicksort: I haven't put any thought into optimizing it. + // I _did_ put thought into making sure it's safe (it will always + // terminate). Worst-case it's O(n^2), but it will usually run in + // in O(n log n). It's well-behaved if the list is already sorted, + // or nearly so. + // + static private void quickSort(Object[] arr, Comparer c, int from, int to) { + if (to <= from) + return; + int mid = (from + to) / 2; + if (mid != from) + swap(arr, mid, from); + Object pivot = arr[from]; // Simple-minded, but reasonable + int highestBelowPivot = from - 1; + int low = from+1; + int high = to; + // We now move low and high toward each other, maintaining the + // invariants: + // arr[i] <= pivot for all i < low + // arr[i] > pivot for all i > high + // As long as these invariants hold, and every iteration makes + // progress, we are safe. + while (low <= high) { + int cmp = c.compare(arr[low], pivot); + if (cmp <= 0) { // arr[low] <= pivot + if (cmp < 0) { + highestBelowPivot = low; + } + low++; + } else { + int c2; + for (;;) { + // arr[high] > pivot: + c2 = c.compare(arr[high], pivot); + if (c2 > 0) { + high--; + if (low > high) { + break; + } + } else { + break; + } + } + // At this point, low is never == high, BTW + if (low <= high) { + swap(arr, low, high); + if (c2 < 0) { + highestBelowPivot = low; + } + low++; + high--; + } + } + } + // At this point, low == high+1 + // Now we just need to sort from from..highestBelowPivot + // and from high+1..to + if (highestBelowPivot > from) { + // pivot == pivot, so ensure algorithm terminates + swap(arr, from, highestBelowPivot); + quickSort(arr, c, from, highestBelowPivot-1); + } + quickSort(arr, c, high+1, to); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/util/Comparer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/util/Comparer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.util; + +/** + * Base class for comparison of two objects. + * @see VectorSorter + * + * @author Bill Foote + */ + +abstract public class Comparer { + + /** + * @return a number <, == or > 0 depending on lhs compared to rhs + * @see java.lang.String.compareTo + **/ + abstract public int compare(Object lhs, Object rhs); +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/util/CompositeEnumeration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/util/CompositeEnumeration.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.util; + +import java.util.Enumeration; +import java.util.NoSuchElementException; +import jdk.test.lib.hprof.model.JavaHeapObject; + +public class CompositeEnumeration implements Enumeration { + Enumeration e1; + Enumeration e2; + + public CompositeEnumeration(Enumeration e1, Enumeration e2) { + this.e1 = e1; + this.e2 = e2; + } + + public boolean hasMoreElements() { + return e1.hasMoreElements() || e2.hasMoreElements(); + } + + public JavaHeapObject nextElement() { + if (e1.hasMoreElements()) { + return e1.nextElement(); + } + + if (e2.hasMoreElements()) { + return e2.nextElement(); + } + + throw new NoSuchElementException(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/util/Misc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/util/Misc.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.util; +import java.util.*; + +/** + * Miscellaneous functions I couldn't think of a good place to put. + * + * @author Bill Foote + */ + + +public class Misc { + + private static char[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + public final static String toHex(int addr) { + char[] buf = new char[8]; + int i = 0; + for (int s = 28; s >= 0; s -= 4) { + buf[i++] = digits[(addr >> s) & 0xf]; + } + return "0x" + new String(buf); + } + + public final static String toHex(long addr) { + return "0x" + Long.toHexString(addr); + } + + public final static long parseHex(String value) { + long result = 0; + if (value.length() < 2 || value.charAt(0) != '0' || + value.charAt(1) != 'x') { + return -1L; + } + for(int i = 2; i < value.length(); i++) { + result *= 16; + char ch = value.charAt(i); + if (ch >= '0' && ch <= '9') { + result += (ch - '0'); + } else if (ch >= 'a' && ch <= 'f') { + result += (ch - 'a') + 10; + } else if (ch >= 'A' && ch <= 'F') { + result += (ch - 'A') + 10; + } else { + throw new NumberFormatException("" + ch + + " is not a valid hex digit"); + } + } + return result; + } + + public static String encodeHtml(String str) { + final int len = str.length(); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < len; i++) { + char ch = str.charAt(i); + if (ch == '<') { + sb.append("<"); + } else if (ch == '>') { + sb.append(">"); + } else if (ch == '"') { + sb.append("""); + } else if (ch == '\'') { + sb.append("'"); + } else if (ch == '&') { + sb.append("&"); + } else if (ch < ' ') { + sb.append("&#").append((int)ch).append(';'); + } else { + int c = (ch & 0xFFFF); + if (c > 127) { + sb.append("&#").append(c).append(';'); + } else { + sb.append(ch); + } + } + } + return sb.toString(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/hprof/util/VectorSorter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/hprof/util/VectorSorter.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.util; +import java.util.*; + +/** + * A singleton utility class that sorts a vector. + *

+ * Use: + *

+ *
+ *  Vector v =   ;
+ *  VectorSorter.sort(v, new Comparer() {
+ *      public int compare(Object lhs, Object rhs) {
+ *          return ((String) lhs).compareTo((String) rhs);
+ *      }
+ *  });
+ * 
+ * + * @author Bill Foote + */ + + +public class VectorSorter { + + /** + * Sort the given vector, using c for comparison + **/ + static public void sort(Vector v, Comparer c) { + quickSort(v, c, 0, v.size()-1); + } + + + /** + * Sort a vector of strings, using String.compareTo() + **/ + static public void sortVectorOfStrings(Vector v) { + sort(v, new Comparer() { + public int compare(Object lhs, Object rhs) { + return ((String) lhs).compareTo((String) rhs); + } + }); + } + + + static private void swap(Vector v, int a, int b) { + Object tmp = v.elementAt(a); + v.setElementAt(v.elementAt(b), a); + v.setElementAt(tmp, b); + } + + // + // Sorts v between from and to, inclusive. This is a quick, off-the-top- + // of-my-head quicksort: I haven't put any thought into optimizing it. + // I _did_ put thought into making sure it's safe (it will always + // terminate). Worst-case it's O(n^2), but it will usually run in + // in O(n log n). It's well-behaved if the list is already sorted, + // or nearly so. + // + static private void quickSort(Vector v, Comparer c, int from, int to) { + if (to <= from) + return; + int mid = (from + to) / 2; + if (mid != from) + swap(v, mid, from); + Object pivot = v.elementAt(from); + // Simple-minded, but reasonable + int highestBelowPivot = from - 1; + int low = from+1; + int high = to; + // We now move low and high toward eachother, maintaining the + // invariants: + // v[i] <= pivot for all i < low + // v[i] > pivot for all i > high + // As long as these invariants hold, and every iteration makes + // progress, we are safe. + while (low <= high) { + int cmp = c.compare(v.elementAt(low), pivot); + if (cmp <= 0) { // v[low] <= pivot + if (cmp < 0) { + highestBelowPivot = low; + } + low++; + } else { + int c2; + for (;;) { + c2 = c.compare(v.elementAt(high), pivot); + // v[high] > pivot: + if (c2 > 0) { + high--; + if (low > high) { + break; + } + } else { + break; + } + } + // At this point, low is never == high + if (low <= high) { + swap(v, low, high); + if (c2 < 0) { + highestBelowPivot = low; + } + low++; + high--; + } + } + } + // Now we just need to sort from from..highestBelowPivot + // and from high+1..to + if (highestBelowPivot > from) { + // pivot == pivot, so ensure algorithm terminates + swap(v, from, highestBelowPivot); + quickSort(v, c, from, highestBelowPivot-1); + } + quickSort(v, c, high+1, to); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/AppExecutorHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,80 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + + +/** + * Helper class for running applications with enabled JFR recording + */ +public class AppExecutorHelper { + + /** + * Executes an application with enabled JFR and writes collected events + * to the given output file. + * Which events to track and other parameters are taken from the setting .jfc file. + * + * @param setting JFR settings file(optional) + * @param jfrFilename JFR resulting recording filename(optional) + * @param additionalVMFlags additional VM flags passed to the java(optional) + * @param className name of the class to execute + * @param classArguments arguments passed to the class(optional) + * @return output analyzer for executed application + */ + public static OutputAnalyzer executeAndRecord(String settings, String jfrFilename, String[] additionalVmFlags, + String className, String... classArguments) throws Exception { + List arguments = new ArrayList<>(); + String baseStartFlightRecording = "-XX:StartFlightRecording"; + String additionalStartFlightRecording = ""; + + if (additionalVmFlags != null) { + Collections.addAll(arguments, additionalVmFlags); + } + + if (settings != null & jfrFilename != null) { + additionalStartFlightRecording = String.format("=settings=%s,filename=%s", settings, jfrFilename); + } else if (settings != null) { + additionalStartFlightRecording = String.format("=settings=%s", settings); + } else if (jfrFilename != null) { + additionalStartFlightRecording = String.format("=filename=%s", jfrFilename); + } + arguments.add(baseStartFlightRecording + additionalStartFlightRecording); + + arguments.add(className); + if (classArguments.length > 0) { + Collections.addAll(arguments, classArguments); + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, arguments.toArray(new String[0])); + return ProcessTools.executeProcess(pb); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/CommonHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/CommonHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,117 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.fail; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.RecordingState; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; + + +/** + * Common helper class. + */ +public final class CommonHelper { + + private static RecordedEvent timeStampCounterEvent; + + public static void verifyException(VoidFunction f, String msg, Class expectedException) throws Throwable { + try { + f.run(); + } catch (Throwable t) { + if (expectedException.isAssignableFrom(t.getClass())) { + return; + } + t.printStackTrace(); + assertEquals(t.getClass(), expectedException, "Wrong exception class"); + } + fail("Missing Exception for: " + msg); + } + + public static Recording verifyExists(long recId, List recordings) { + for (Recording r : recordings) { + if (recId == r.getId()) { + return r; + } + } + Asserts.fail("Recording not found, id=" + recId); + return null; + } + + + public static void waitForRecordingState(Recording r, RecordingState expectedState) throws Exception { + while (r.getState() != expectedState) { + Thread.sleep(20); + } + } + + public static void verifyRecordingState(Recording r, RecordingState expectedState) throws Exception { + assertEquals(expectedState, r.getState(), "Wrong state"); + } + + public static boolean hasFastTimeEnabled() throws Exception { + return getTimeStampCounterEvent().getValue("fastTimeEnabled"); + } + + private synchronized static RecordedEvent getTimeStampCounterEvent() throws IOException, Exception { + if (timeStampCounterEvent == null) { + try (Recording r = new Recording()) { + r.enable(EventNames.CPUTimeStampCounter); + r.start(); + r.stop(); + Path p = Utils.createTempFile("timestamo", ".jfr"); + r.dump(p); + List events = RecordingFile.readAllEvents(p); + Files.deleteIfExists(p); + if (events.isEmpty()) { + throw new Exception("Could not locate CPUTimeStampCounter event"); + } + timeStampCounterEvent = events.get(0); + } + } + return timeStampCounterEvent; + } + + public static void waitForSystemCurrentMillisToChange() { + long t = System.currentTimeMillis(); + while (t == System.currentTimeMillis()) { + try { + Thread.sleep(2); + } catch (InterruptedException e) { + throw new Error("Sleep interupted", e); + } + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/EventField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/EventField.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,149 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedObject; +import jdk.test.lib.Asserts; + + +public final class EventField { + public final RecordedObject event; + public final ValueDescriptor desc; + + public EventField(RecordedObject event, ValueDescriptor valueDescriptor) { + this.event = event; + this.desc = valueDescriptor; + } + + @SuppressWarnings("unchecked") + public > boolean isEqual(T value) { + return value == (T)getValue(); + } + + @SuppressWarnings("unchecked") + public > EventField equal(T value) { + doAssert(()-> Asserts.assertEquals((T)getValue(), value, getErrMsg("Value not equal to " + value))); + return this; + } + + @SuppressWarnings("unchecked") + public > EventField notEqual(T value) { + doAssert(()-> Asserts.assertNotEquals((T)getValue(), value, getErrMsg("Value equal to " + value))); + return this; + } + + @SuppressWarnings("unchecked") + public > EventField above(T value) { + doAssert(()-> Asserts.assertGreaterThan((T)getValue(), value, getErrMsg("Value not above " + value))); + return this; + } + + @SuppressWarnings("unchecked") + public > EventField below(T value) { + doAssert(()-> Asserts.assertLessThan((T)getValue(), value, getErrMsg("Value not below " + value))); + return this; + } + + @SuppressWarnings("unchecked") + public > EventField atLeast(T value) { + doAssert(()-> Asserts.assertGreaterThanOrEqual((T)getValue(), value, getErrMsg("Value not atLeast" + value))); + return this; + } + + @SuppressWarnings("unchecked") + public > EventField atMost(T value) { + doAssert(()-> Asserts.assertLessThanOrEqual((T)getValue(), value, getErrMsg("Value not atMost " + value))); + return this; + } + + public > EventField instring(String part) { + final String value = getValue(); + doAssert(()-> Asserts.assertTrue(value.contains(part), getErrMsg("Value does not contain '" + part +"'"))); + return this; + } + + @SuppressWarnings("unchecked") + public T getValue() { + return (T)event.getValue(desc.getName()); + } + + public EventField notNull() { + doAssert(()-> Asserts.assertNotNull(getValue(), getErrMsg("Field is null"))); + return this; + } + + public EventField isNull() { + doAssert(()-> Asserts.assertNull(getValue(), getErrMsg("Field is not null"))); + return this; + } + + public EventField notEmpty() { + notNull(); + final String s = getValue(); + doAssert(()-> Asserts.assertFalse(s.isEmpty(), getErrMsg("Field is empty"))); + return this; + } + + private void doAssert(AssertFunction f) { + try { + f.doAssert(); + } catch (RuntimeException e) { + System.out.printf("Error: %s%nFailed event:%n%s%n", e.getMessage(), event.toString()); + throw e; + } + } + + public EventField containsAny(String... allowed) { + final String value = getValue(); + final List allowedValues = Arrays.asList(allowed); + boolean contains = false; + for(String allowedValue : allowed) { + if (value.contains(allowedValue)) { + contains = true; + } + } + if (!contains) { + doAssert(()-> Asserts.fail(getErrMsg(String.format("Value not in (%s)", + allowedValues.stream().collect(Collectors.joining(", ")))))); + } + return this; + } + + private String getErrMsg(String msg) { + final String name = desc.getName(); + final Object value = event.getValue(name); + return String.format("%s, field='%s', value='%s'", msg, name, value); + } + + @FunctionalInterface + public interface AssertFunction { + void doAssert(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/EventNames.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/EventNames.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import jdk.jfr.EventType; + +/** + * Contains id for events that are shipped with the JDK. + * + */ +public class EventNames { + + public final static String PREFIX = "jdk."; + private static final String GC_CATEGORY = "GC"; + + // JVM Configuration + public final static String JVMInformation = PREFIX + "JVMInformation"; + public final static String InitialSystemProperty = PREFIX + "InitialSystemProperty"; + public final static String IntFlag = PREFIX + "IntFlag"; + public final static String UnsignedIntFlag = PREFIX + "UnsignedIntFlag"; + public final static String LongFlag = PREFIX + "LongFlag"; + public final static String UnsignedLongFlag = PREFIX + "UnsignedLongFlag"; + public final static String DoubleFlag = PREFIX + "DoubleFlag"; + public final static String BooleanFlag = PREFIX + "BooleanFlag"; + public final static String StringFlag = PREFIX + "StringFlag"; + public final static String IntFlagChanged = PREFIX + "IntFlagChanged"; + public final static String UnsignedIntFlagChanged = PREFIX + "UnsignedIntFlagChanged"; + public final static String LongFlagChanged = PREFIX + "LongFlagChanged"; + public final static String UnsignedLongFlagChanged = PREFIX + "UnsignedLongFlagChanged"; + public final static String DoubleFlagChanged = PREFIX + "DoubleFlagChanged"; + public final static String BooleanFlagChanged = PREFIX + "BooleanFlagChanged"; + public final static String StringFlagChanged = PREFIX + "StringFlagChanged"; + + // Runtime + public final static String ThreadStart = PREFIX + "ThreadStart"; + public final static String ThreadEnd = PREFIX + "ThreadEnd"; + public final static String ThreadSleep = PREFIX + "ThreadSleep"; + public final static String ThreadPark = PREFIX + "ThreadPark"; + public final static String JavaMonitorEnter = PREFIX + "JavaMonitorEnter"; + public final static String JavaMonitorWait = PREFIX + "JavaMonitorWait"; + public final static String JavaMonitorInflate = PREFIX + "JavaMonitorInflate"; + public final static String ClassLoad = PREFIX + "ClassLoad"; + public final static String ClassDefine = PREFIX + "ClassDefine"; + public final static String ClassUnload = PREFIX + "ClassUnload"; + public final static String SafepointBegin = PREFIX + "SafepointBegin"; + public final static String SafepointStateSynchronization = PREFIX + "SafepointStateSynchronization"; + public final static String SafepointCleanup = PREFIX + "SafepointCleanup"; + public final static String SafepointCleanupTask = PREFIX + "SafepointCleanupTask"; + public final static String SafepointEnd = PREFIX + "SafepointEnd"; + public final static String ExecuteVMOperation = PREFIX + "ExecuteVMOperation"; + public final static String Shutdown = PREFIX + "Shutdown"; + public final static String JavaThreadStatistics = PREFIX + "JavaThreadStatistics"; + public final static String ClassLoadingStatistics = PREFIX + "ClassLoadingStatistics"; + public final static String ClassLoaderStatistics = PREFIX + "ClassLoaderStatistics"; + public final static String ThreadAllocationStatistics = PREFIX + "ThreadAllocationStatistics"; + public final static String ExecutionSample = PREFIX + "ExecutionSample"; + public final static String NativeMethodSample = PREFIX + "NativeMethodSample"; + public final static String ThreadDump = PREFIX + "ThreadDump"; + public final static String OldObjectSample = PREFIX + "OldObjectSample"; + public final static String BiasedLockRevocation = PREFIX + "BiasedLockRevocation"; + public final static String BiasedLockSelfRevocation = PREFIX + "BiasedLockSelfRevocation"; + public final static String BiasedLockClassRevocation = PREFIX + "BiasedLockClassRevocation"; + public final static String SymbolTableStatistics = PREFIX + "SymbolTableStatistics"; + public final static String StringTableStatistics = PREFIX + "StringTableStatistics"; + public final static String PlaceholderTableStatistics = PREFIX + "PlaceholderTableStatistics"; + public final static String LoaderConstraintsTableStatistics = PREFIX + "LoaderConstraintsTableStatistics"; + public final static String ProtectionDomainCacheTableStatistics = PREFIX + "ProtectionDomainCacheTableStatistics"; + // This event is hard to test + public final static String ReservedStackActivation = PREFIX + "ReservedStackActivation"; + + // GC + public final static String GCHeapSummary = PREFIX + "GCHeapSummary"; + public final static String MetaspaceSummary = PREFIX + "MetaspaceSummary"; + public final static String MetaspaceGCThreshold = PREFIX + "MetaspaceGCThreshold"; + public final static String MetaspaceAllocationFailure = PREFIX + "MetaspaceAllocationFailure"; + public final static String MetaspaceOOM = PREFIX + "MetaspaceOOM"; + public final static String MetaspaceChunkFreeListSummary = PREFIX + "MetaspaceChunkFreeListSummary"; + public final static String PSHeapSummary = PREFIX + "PSHeapSummary"; + public final static String G1HeapSummary = PREFIX + "G1HeapSummary"; + public final static String G1HeapRegionInformation = PREFIX + "G1HeapRegionInformation"; + public final static String G1HeapRegionTypeChange = PREFIX + "G1HeapRegionTypeChange"; + public final static String TenuringDistribution = PREFIX + "TenuringDistribution"; + public final static String GarbageCollection = PREFIX + "GarbageCollection"; + public final static String ParallelOldGarbageCollection = PREFIX + "ParallelOldGarbageCollection"; + public final static String ParallelOldCollection = ParallelOldGarbageCollection; + public final static String YoungGarbageCollection = PREFIX + "YoungGarbageCollection"; + public final static String OldGarbageCollection = PREFIX + "OldGarbageCollection"; + public final static String G1GarbageCollection = PREFIX + "G1GarbageCollection"; + public final static String G1MMU = PREFIX + "G1MMU"; + public final static String EvacuationInformation = PREFIX + "EvacuationInformation"; + public final static String GCReferenceStatistics = PREFIX + "GCReferenceStatistics"; + public final static String ObjectCountAfterGC = PREFIX + "ObjectCountAfterGC"; + public final static String PromoteObjectInNewPLAB = PREFIX + "PromoteObjectInNewPLAB"; + public final static String PromoteObjectOutsidePLAB = PREFIX + "PromoteObjectOutsidePLAB"; + public final static String PromotionFailed = PREFIX + "PromotionFailed"; + public final static String EvacuationFailed = PREFIX + "EvacuationFailed"; + public final static String ConcurrentModeFailure = PREFIX + "ConcurrentModeFailure"; + public final static String GCPhasePause = PREFIX + "GCPhasePause"; + public final static String GCPhasePauseLevel1 = PREFIX + "GCPhasePauseLevel1"; + public final static String GCPhasePauseLevel2 = PREFIX + "GCPhasePauseLevel2"; + public final static String GCPhasePauseLevel3 = PREFIX + "GCPhasePauseLevel3"; + public final static String GCPhasePauseLevel4 = PREFIX + "GCPhasePauseLevel4"; + public final static String ObjectCount = PREFIX + "ObjectCount"; + public final static String GCConfiguration = PREFIX + "GCConfiguration"; + public final static String GCSurvivorConfiguration = PREFIX + "GCSurvivorConfiguration"; + public final static String GCTLABConfiguration = PREFIX + "GCTLABConfiguration"; + public final static String GCHeapConfiguration = PREFIX + "GCHeapConfiguration"; + public final static String YoungGenerationConfiguration = PREFIX + "YoungGenerationConfiguration"; + public final static String G1AdaptiveIHOP = PREFIX + "G1AdaptiveIHOP"; + public final static String G1EvacuationYoungStatistics = PREFIX + "G1EvacuationYoungStatistics"; + public final static String G1EvacuationOldStatistics = PREFIX + "G1EvacuationOldStatistics"; + public final static String G1BasicIHOP = PREFIX + "G1BasicIHOP"; + public final static String AllocationRequiringGC = PREFIX + "AllocationRequiringGC"; + public final static String GCPhaseParallel = PREFIX + "GCPhaseParallel"; + public final static String GCPhaseConcurrent = PREFIX + "GCPhaseConcurrent"; + + // Compiler + public final static String Compilation = PREFIX + "Compilation"; + public final static String CompilerPhase = PREFIX + "CompilerPhase"; + public final static String CompilationFailure = PREFIX + "CompilationFailure"; + public final static String CompilerInlining = PREFIX + "CompilerInlining"; + public final static String CompilerStatistics = PREFIX + "CompilerStatistics"; + public final static String CompilerConfiguration = PREFIX + "CompilerConfiguration"; + public final static String CodeCacheStatistics = PREFIX + "CodeCacheStatistics"; + public final static String CodeCacheConfiguration = PREFIX + "CodeCacheConfiguration"; + public final static String CodeSweeperStatistics = PREFIX + "CodeSweeperStatistics"; + public final static String CodeSweeperConfiguration = PREFIX + "CodeSweeperConfiguration"; + public final static String SweepCodeCache = PREFIX + "SweepCodeCache"; + public final static String CodeCacheFull = PREFIX + "CodeCacheFull"; + public final static String ObjectAllocationInNewTLAB = PREFIX + "ObjectAllocationInNewTLAB"; + public final static String ObjectAllocationOutsideTLAB = PREFIX + "ObjectAllocationOutsideTLAB"; + + // OS + public final static String OSInformation = PREFIX + "OSInformation"; + public final static String CPUInformation = PREFIX + "CPUInformation"; + public final static String CPULoad = PREFIX + "CPULoad"; + public final static String ThreadCPULoad = PREFIX + "ThreadCPULoad"; + public final static String SystemProcess = PREFIX + "SystemProcess"; + public final static String ThreadContextSwitchRate = PREFIX + "ThreadContextSwitchRate"; + public final static String InitialEnvironmentVariable = PREFIX + "InitialEnvironmentVariable"; + public final static String NativeLibrary = PREFIX + "NativeLibrary"; + public final static String PhysicalMemory = PREFIX + "PhysicalMemory"; + public final static String NetworkUtilization = PREFIX + "NetworkUtilization"; + + // JDK + public static final String FileForce = PREFIX + "FileForce"; + public static final String FileRead = PREFIX + "FileRead"; + public static final String FileWrite = PREFIX + "FileWrite"; + public static final String SocketRead = PREFIX + "SocketRead"; + public static final String SocketWrite = PREFIX + "SocketWrite"; + public final static String ExceptionStatistics = PREFIX + "ExceptionStatistics"; + public final static String JavaExceptionThrow = PREFIX + "JavaExceptionThrow"; + public final static String JavaErrorThrow = PREFIX + "JavaErrorThrow"; + public final static String ModuleRequire = PREFIX + "ModuleRequire"; + public final static String ModuleExport = PREFIX + "ModuleExport"; + public final static String TLSHandshake = PREFIX + "TLSHandshake"; + public final static String X509Certificate = PREFIX + "X509Certificate"; + public final static String X509Validation = PREFIX + "X509Validation"; + public final static String SecurityProperty = PREFIX + "SecurityPropertyModification"; + + // Flight Recorder + public final static String DumpReason = PREFIX + "DumpReason"; + public final static String DataLoss = PREFIX + "DataLoss"; + public final static String CPUTimeStampCounter = PREFIX + "CPUTimeStampCounter"; + public final static String ActiveRecording = PREFIX + "ActiveRecording"; + public final static String ActiveSetting = PREFIX + "ActiveSetting"; + + public static boolean isGcEvent(EventType et) { + return et.getCategoryNames().contains(GC_CATEGORY); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/EventTypePrototype.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/EventTypePrototype.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,80 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import java.util.ArrayList; +import java.util.List; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.Name; +import jdk.jfr.ValueDescriptor; + +public final class EventTypePrototype { + private final List fields; + private final List annotations; + private final String name; + + public EventTypePrototype(String name, List as, List fields) { + this.annotations = new ArrayList<>(as); + this.annotations.add(new AnnotationElement(Name.class, name)); + this.fields = fields; + this.name = name; + } + + public EventTypePrototype(String name) { + this(name, new ArrayList<>(), new ArrayList<>()); + } + + public int getFieldIndex(String key) { + int index = 0; + for (ValueDescriptor f : fields) { + if (f.getName().equals(key)) { + return index; + } + index++; + } + throw new NoSuchFieldError(key); + } + + public void addField(ValueDescriptor fieldDescriptor) { + fields.add(fieldDescriptor); + } + + public void addAnnotation(AnnotationElement annotation) { + annotations.add(annotation); + } + + public List getFields() { + return fields; + } + + public List getAnnotations() { + return annotations; + } + + public String getName() { + return name; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/EventVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/EventVerifier.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,53 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import jdk.jfr.consumer.RecordedEvent; + +public abstract class EventVerifier { + protected final RecordedEvent event; + + public EventVerifier(RecordedEvent event) { + this.event = event; + } + + public > void verifyEquals(String name, T value) { + Events.assertField(event, name).equal(value); + } + + public void verifyContains(String name, String value) { + Events.assertField(event, name).containsAny(value); + } + + protected long gigabytes(int num) { + return num * 1024L * 1024L * 1024L; + } + + protected long megabytes(int num) { + return num * 1024L * 1024L; + } + + public abstract void verify() throws Exception; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/Events.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/Events.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,366 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertFalse; +import static jdk.test.lib.Asserts.assertNotNull; +import static jdk.test.lib.Asserts.assertTrue; +import static jdk.test.lib.Asserts.fail; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; +import java.util.List; + +import jdk.jfr.AnnotationElement; +import jdk.jfr.EventType; +import jdk.jfr.Recording; +import jdk.jfr.SettingDescriptor; +import jdk.jfr.Timespan; +import jdk.jfr.Timestamp; +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.Asserts; +import jdk.jfr.consumer.RecordedClass; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordedThread; +import jdk.jfr.consumer.RecordedThreadGroup; + + +/** + * Helper class to verify RecordedEvent content + */ +public class Events { + + public static EventField assertField(RecordedEvent event, String name) { + String[] partNames = name.split("\\."); + RecordedObject struct = event; + try { + for (int i=0; i valueDescriptors = struct.getFields(); + for (ValueDescriptor d : valueDescriptors) { + if (name.equals(d.getName())) { + return d; + } + } + System.out.printf("Failed struct:%s", struct.toString()); + fail(String.format("Field %s not in struct", name)); + return null; + } + + public static void hasEvents(List events) { + assertFalse(events.isEmpty(), "No events"); + } + + public static void hasEvents(RecordingFile file) { + assertTrue(file.hasMoreEvents(), "No events"); + } + + public static void assertEventThread(RecordedEvent event) { + RecordedThread eventThread = event.getThread(); + if (eventThread == null) { + System.out.printf("Failed event:%n%s%n", event.toString()); + fail("No thread in event"); + } + } + + public static void assertJavaMethod(RecordedEvent event) { + assertField(event, "method.name").notEmpty(); + assertField(event, "method.descriptor").notEmpty(); + assertField(event, "method.modifiers").atLeast(0); + assertField(event, "method.hidden"); + assertField(event, "method.type.name").notEmpty(); + assertField(event, "method.type.modifiers").atLeast(0); + } + + public static void assertEventThread(RecordedEvent event, Thread thread) { + assertThread(event.getThread(), thread); + } + + public static void assertEventThread(RecordedEvent event, String structName, Thread thread) { + assertThread(assertField(event, structName).notNull().getValue(), thread); + } + + public static void assertDuration(RecordedEvent event, String name, Duration duration) { + assertEquals(event.getDuration(name), duration); + } + + public static void assertInstant(RecordedEvent event, String name, Instant instant) { + assertEquals(event.getInstant(name), instant); + } + + public static void assertMissingValue(RecordedEvent event, String name) { + ValueDescriptor v = event.getEventType().getField(name); + if (v.getAnnotation(Timespan.class) != null) { + Duration d = event.getDuration(name); + assertTrue(d.getSeconds() == Long.MIN_VALUE && d.getNano() == 0); + return; + } + if (v.getAnnotation(Timestamp.class) != null) { + Instant instant = event.getInstant(name); + assertTrue(instant.equals(Instant.MIN)); + return; + } + if (v.getTypeName().equals("double")) { + double d = event.getDouble(name); + assertTrue(Double.isNaN(d) || d == Double.NEGATIVE_INFINITY); + return; + } + if (v.getTypeName().equals("float")) { + float f = event.getFloat(name); + assertTrue(Float.isNaN(f) || f == Float.NEGATIVE_INFINITY); + return; + } + if (v.getTypeName().equals("int")) { + int i = event.getInt(name); + assertTrue(i == Integer.MIN_VALUE); + return; + } + if (v.getTypeName().equals("long")) { + assertEquals(event.getLong(name), Long.MIN_VALUE); + return; + } + Object o = event.getValue(name); + Asserts.assertNull(o); + } + + private static void assertThread(RecordedThread eventThread, Thread thread) { + assertNotNull(eventThread, "Thread in event was null"); + assertEquals(eventThread.getJavaThreadId(), thread.getId(), "Wrong thread id"); + assertEquals(eventThread.getJavaName(), thread.getName(), "Wrong thread name"); + + ThreadGroup threadGroup = thread.getThreadGroup(); + RecordedThreadGroup eventThreadGroup = eventThread.getThreadGroup(); + assertNotNull(eventThreadGroup, "eventThreadGroup was null"); + + // Iterate and check all threadGroups + while (eventThreadGroup != null) { + final String groupName = eventThreadGroup.getName(); + if (threadGroup != null) { + assertEquals(groupName, threadGroup.getName(), "Wrong threadGroup name"); + threadGroup = threadGroup.getParent(); + } else { + assertNotNull(groupName, "threadGroup name was null"); + assertFalse(groupName.isEmpty(), "threadGroup name was empty"); + } + eventThreadGroup = eventThreadGroup.getParent(); + } + } + + public static boolean hasField(RecordedEvent event, String name) { + return event.getFields().stream().map(vd -> vd.getName()).anyMatch(s -> s.equals(name)); + } + + public static boolean isEventType(RecordedEvent event, String typeName) { + return typeName.equals(event.getEventType().getName()); + } + + + /** + * Creates a list of events from a recording. + * + * @param recording recording, not {@code null} + * @return an a list, not null + * @throws IOException if an event set could not be created due to I/O + * errors. + */ + public static List fromRecording(Recording recording) throws IOException { + return RecordingFile.readAllEvents(makeCopy(recording)); + } + + public static RecordingFile copyTo(Recording r) throws IOException { + return new RecordingFile(makeCopy(r)); + } + + private static Path makeCopy(Recording recording) throws IOException { + Path p = recording.getDestination(); + if (p == null) { + File directory = new File("."); + // FIXME: Must come up with a way to give human-readable name + // this will at least not clash when running parallel. + ProcessHandle h = ProcessHandle.current(); + p = new File(directory.getAbsolutePath(), "recording-" + recording.getId() + "-pid" + h.pid() + ".jfr").toPath(); + recording.dump(p); + } + return p; + } + + public static void hasAnnotation(ValueDescriptor field, Class annotationClass) throws Exception { + AnnotationElement a = getAnnotation(field, annotationClass); + if (a == null) { + throw new Exception("Expected " + annotationClass.getSimpleName() + " on field " + field.getName()); + } + } + + public static void assertAnnotation(ValueDescriptor field, Class annotationClass, String value) throws Exception { + AnnotationElement a = getAnnotation(field, annotationClass); + Object v = a.getValue("value"); + if (!v.equals(value)) { + throw new Exception("Expected " + annotationClass.getSimpleName() + " on field " + field.getName() + " to have value " + value + ", but got " + v); + } + } + + // candidate for moving into API + public static AnnotationElement getAnnotation(ValueDescriptor v, Class clazz) throws Exception { + for (AnnotationElement a : v.getAnnotationElements()) { + if (a.getTypeName().equals(clazz.getName())) { + return a; + } + } + + throw new Exception("Could not find annotation " + clazz.getName()); + } + + // candidate for moving into API + public static AnnotationElement getAnnotationByName(EventType t, String name) throws Exception { + for (AnnotationElement a : t.getAnnotationElements()) { + if (a.getTypeName().equals(name)) { + return a; + } + } + throw new Exception("Could not find annotation '" + name + " in type " + t.getName()); + } + + // candidate for moving into API + public static SettingDescriptor getSetting(EventType type, String name) { + for (SettingDescriptor s : type.getSettingDescriptors()) { + if (s.getName().equals(name)) { + return s; + } + } + throw new IllegalArgumentException("Could not setting with name " + name); + } + + public static void hasEvent(Recording r, String name) throws IOException { + List events = fromRecording(r); + Events.hasEvents(events); + Events.hasEvent(events, name); + } + + public static void hasEvent(List events, String name) throws IOException { + if (!containsEvent(events, name)) { + Asserts.fail("Missing event " + name + " in recording " + events.toString()); + } + } + + public static void hasNotEvent(List events, String name) throws IOException { + if (containsEvent(events, name)) { + Asserts.fail("Rercording should not contain event " + name + " " + events.toString()); + } + } + + private static boolean containsEvent(List events, String name) { + for (RecordedEvent event : events) { + if (event.getEventType().getName().equals(name)) { + return true; + } + } + return false; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/FileHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/FileHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,124 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import java.io.File; +import java.io.IOException; +import java.nio.file.AccessDeniedException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; + +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; +import jdk.test.lib.Asserts; + +/** + * Common helper class. + */ +public class FileHelper { + + public static Path getDest(String subPath) throws IOException { + Path path = Paths.get(subPath + "/test.jfr"); + Path parent = path.getParent(); + if (parent == null) { + throw new IOException("No parent cound be found for path " + subPath); + } + Files.createDirectories(parent); + return path; + } + + public static Path createLongDir(Path root) throws IOException { + final int minPathLength = 400; + StringBuilder buff = new StringBuilder(); + buff.append(root.toString()); + while (buff.length() < minPathLength) { + buff.append("/veryLongPath012345678901234567890123456789"); + } + Path path = Paths.get(buff.toString()); + System.out.println("long dir=" + path); + Files.createDirectories(path); + return path; + } + + public static Path getDestReadOnly(String subPath) throws IOException { + final Path path = getDest(subPath); + Path parent = path.getParent(); + if (parent == null) { + throw new IOException("No parent cound be found for path " + subPath); + } + parent.toFile().setReadOnly(); + return path; + } + + public static Path createReadOnlyFile(Path path) throws IOException { + final Path createdPath = Files.createFile(path); + createdPath.toFile().setReadOnly(); + return createdPath; + } + + public static Path createReadOnlyDir(Path path) throws IOException { + final Path createdPath = Files.createDirectories(path); + createdPath.toFile().setReadOnly(); + return createdPath; + } + + public static Path getDestNotExist() { + return Paths.get(".", "thisDirDoesNotExist/test.jfr"); + } + + public static boolean isReadOnlyPath(Path path) throws IOException { + // Files.isWritable(path) can not really be trusted. At least not on Windows. + // If path is a directory, we try to create a new file in it. + if (Files.isDirectory(path)) { + try { + Path f = Files.createFile(Paths.get(path.toString(), "dummyFileToCheckReadOnly")); + System.out.printf("Dir is not read-only, created %s, exists=%b%n", f, Files.exists(f)); + return false; + } catch (AccessDeniedException e) { + System.out.printf("'%s' verified read-only by %s%n", path, e.toString()); + return true; + } + } else { + boolean isReadOnly = !Files.isWritable(path); + System.out.format("isReadOnly '%s': %b%n", path, isReadOnly); + return isReadOnly; + } + } + + public static void verifyRecording(File file) throws Exception { + Asserts.assertTrue(file.exists(), file.getAbsolutePath() + " does not exist"); + Asserts.assertTrue(file.isFile(), file.getAbsolutePath() + " is not a file"); + Asserts.assertGreaterThan(file.length(), 0L, "Size of recording is 0."); + List events = RecordingFile.readAllEvents(file.toPath()); + for (RecordedEvent event : events) { + System.out.printf("First event in recording '%s':%n%s", file.getName(), event); + return; + } + Asserts.fail("No events in file " + file.getName()); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/GCHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/GCHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,467 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import static jdk.test.lib.Asserts.assertEquals; +import static jdk.test.lib.Asserts.assertNotEquals; +import static jdk.test.lib.Asserts.assertNotNull; +import static jdk.test.lib.Asserts.assertNull; +import static jdk.test.lib.Asserts.fail; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import jdk.jfr.ValueDescriptor; +import jdk.jfr.consumer.RecordedEvent; + +/** + * Mixed helper classes to test GC events. + */ +public class GCHelper { + public static final String event_garbage_collection = EventNames.GarbageCollection; + public static final String event_young_garbage_collection = EventNames.YoungGarbageCollection; + public static final String event_old_garbage_collection = EventNames.OldGarbageCollection; + public static final String event_parold_garbage_collection = EventNames.ParallelOldCollection; + public static final String event_g1_garbage_collection = EventNames.G1GarbageCollection; + public static final String event_heap_summary = EventNames.GCHeapSummary; + public static final String event_heap_ps_summary = EventNames.PSHeapSummary; + public static final String event_heap_metaspace_summary = EventNames.MetaspaceSummary; + public static final String event_reference_statistics = EventNames.GCReferenceStatistics; + public static final String event_phases_pause = EventNames.GCPhasePause; + public static final String event_phases_level_1 = EventNames.GCPhasePauseLevel1; + public static final String event_phases_level_2 = EventNames.GCPhasePauseLevel2; + public static final String event_phases_level_3 = EventNames.GCPhasePauseLevel3; + + public static final String gcG1New = "G1New"; + public static final String gcParNew = "ParNew"; + public static final String gcDefNew = "DefNew"; + public static final String gcParallelScavenge = "ParallelScavenge"; + public static final String gcG1Old = "G1Old"; + public static final String gcG1Full = "G1Full"; + public static final String gcConcurrentMarkSweep = "ConcurrentMarkSweep"; + public static final String gcSerialOld = "SerialOld"; + public static final String gcPSMarkSweep = "PSMarkSweep"; + public static final String gcParallelOld = "ParallelOld"; + public static final String pauseLevelEvent = "GCPhasePauseLevel"; + + private static final List g1HeapRegionTypes; + private static PrintStream defaultErrorLog = null; + + public static int getGcId(RecordedEvent event) { + return Events.assertField(event, "gcId").getValue(); + } + + public static boolean isGcEvent(RecordedEvent event) { + for (ValueDescriptor v : event.getFields()) { + if ("gcId".equals(v.getName())) { + return true; + } + } + return false; + } + +// public static String getEventDesc(RecordedEvent event) { +// final String path = event.getEventType().getName(); +// if (!isGcEvent(event)) { +// return path; +// } +// if (event_garbage_collection.equals(path)) { +// String name = Events.assertField(event, "name").getValue(); +// String cause = Events.assertField(event, "cause").getValue(); +// return String.format("path=%s, gcId=%d, endTime=%d, name=%s, cause=%s, startTime=%d", +// path, getGcId(event), event.getEndTime(), name, cause, event.getStartTime()); +// } else { +// return String.format("path=%s, gcId=%d, endTime=%d", path, getGcId(event), event.getEndTime()); +// } +// } + + public static RecordedEvent getConfigEvent(List events) throws Exception { + for (RecordedEvent event : events) { + if (EventNames.GCConfiguration.equals(event.getEventType().getName())) { + return event; + } + } + fail("Could not find event " + EventNames.GCConfiguration); + return null; + } + + public static void callSystemGc(int num, boolean withGarbage) { + for (int i = 0; i < num; i++) { + if (withGarbage) { + makeGarbage(); + } + System.gc(); + } + } + + private static void makeGarbage() { + Object[] garbage = new Object[1024]; + for (int i = 0; i < 1024; i++) { + garbage[i] = new Object(); + } + } + + // Removes gcEvents with lowest and highest gcID. This is used to filter out + // any incomplete GCs if the recording started/stopped in the middle of a GC. + // We also filters out events without gcId. Those events are not needed. + public static List removeFirstAndLastGC(List events) { + int minGcId = Integer.MAX_VALUE; + int maxGcId = Integer.MIN_VALUE; + // Find min/max gcId + for (RecordedEvent event : events) { + if (Events.hasField(event, "gcId")) { + int gcId = Events.assertField(event, "gcId").getValue(); + minGcId = Math.min(gcId, minGcId); + maxGcId = Math.max(gcId, maxGcId); + } + } + + // Add all events except those with gcId = min/max gcId + List filteredEvents = new ArrayList<>(); + for (RecordedEvent event : events) { + if (Events.hasField(event, "gcId")) { + int gcId = Events.assertField(event, "gcId").getValue(); + if (gcId != minGcId && gcId != maxGcId) { + filteredEvents.add(event); + } + } + } + return filteredEvents; + } + + public static Map beanCollectorTypes = new HashMap<>(); + public static Set collectorOverrides = new HashSet<>(); + public static Map requiredEvents = new HashMap<>(); + + static { + // young GarbageCollectionMXBeans. + beanCollectorTypes.put("G1 Young Generation", true); + beanCollectorTypes.put("Copy", true); + beanCollectorTypes.put("PS Scavenge", true); + beanCollectorTypes.put("ParNew", true); + + // old GarbageCollectionMXBeans. + beanCollectorTypes.put("G1 Old Generation", false); + beanCollectorTypes.put("ConcurrentMarkSweep", false); + beanCollectorTypes.put("PS MarkSweep", false); + beanCollectorTypes.put("MarkSweepCompact", false); + + // List of expected collector overrides. "A.B" means that collector A may use collector B. + collectorOverrides.add("G1Old.G1Full"); + collectorOverrides.add("ConcurrentMarkSweep.SerialOld"); + collectorOverrides.add("SerialOld.PSMarkSweep"); + + requiredEvents.put(gcG1New, new String[] {event_heap_summary, event_young_garbage_collection}); + requiredEvents.put(gcParNew, new String[] {event_heap_summary, event_heap_metaspace_summary, event_phases_pause, event_phases_level_1, event_young_garbage_collection}); + requiredEvents.put(gcDefNew, new String[] {event_heap_summary, event_heap_metaspace_summary, event_phases_pause, event_phases_level_1, event_young_garbage_collection}); + requiredEvents.put(gcParallelScavenge, new String[] {event_heap_summary, event_heap_ps_summary, event_heap_metaspace_summary, event_reference_statistics, event_phases_pause, event_phases_level_1, event_young_garbage_collection}); + requiredEvents.put(gcG1Old, new String[] {event_heap_summary, event_old_garbage_collection}); + requiredEvents.put(gcG1Full, new String[] {event_heap_summary, event_heap_metaspace_summary, event_phases_pause, event_phases_level_1, event_old_garbage_collection}); + requiredEvents.put(gcConcurrentMarkSweep, new String[] {event_phases_pause, event_phases_level_1, event_old_garbage_collection}); + requiredEvents.put(gcSerialOld, new String[] {event_heap_summary, event_heap_metaspace_summary, event_phases_pause, event_phases_level_1, event_old_garbage_collection}); + requiredEvents.put(gcParallelOld, new String[] {event_heap_summary, event_heap_ps_summary, event_heap_metaspace_summary, event_reference_statistics, event_phases_pause, event_phases_level_1, event_old_garbage_collection, event_parold_garbage_collection}); + + String[] g1HeapRegionTypeLiterals = new String[] { + "Free", + "Eden", + "Survivor", + "Starts Humongous", + "Continues Humongous", + "Old", + "Archive" + }; + + g1HeapRegionTypes = Collections.unmodifiableList(Arrays.asList(g1HeapRegionTypeLiterals)); + } + + /** + * Contains all GC events belonging to the same GC (same gcId). + */ + public static class GcBatch { + private List events = new ArrayList<>(); + + public int getGcId() { + if (events.isEmpty()) { + return -1; + } + return GCHelper.getGcId(events.get(0)); + } + + public String getName() { + RecordedEvent endEvent = getEndEvent(); + String name = endEvent == null ? null : Events.assertField(endEvent, "name").getValue(); + return name == null ? "null" : name; + } + + public RecordedEvent getEndEvent() { + return getEvent(event_garbage_collection); + } + + public boolean addEvent(RecordedEvent event) { + if (!events.isEmpty()) { + assertEquals(getGcId(), GCHelper.getGcId(event), "Wrong gcId in event. Error in test code."); + } + boolean isEndEvent = event_garbage_collection.equals(event.getEventType().getName()); + if (isEndEvent) { + // Verify that we have not already got a garbage_collection event with this gcId. + assertNull(getEndEvent(), String.format("Multiple %s for gcId %d", event_garbage_collection, getGcId())); + } + events.add(event); + return isEndEvent; + } + + public boolean isYoungCollection() { + boolean isYoung = containsEvent(event_young_garbage_collection); + boolean isOld = containsEvent(event_old_garbage_collection); + assertNotEquals(isYoung, isOld, "isYoung and isOld was same for batch: " + toString()); + return isYoung; + } + + public int getEventCount() { + return events.size(); + } + + public RecordedEvent getEvent(int index) { + return events.get(index); + } + + public List getEvents() { + return events; + } + + public RecordedEvent getEvent(String eventPath) { + for (RecordedEvent event : events) { + if (eventPath.equals(event.getEventType().getName())) { + return event; + } + } + return null; + } + + public boolean containsEvent(String eventPath) { + return getEvent(eventPath) != null; + } + + public String toString() { + RecordedEvent endEvent = getEndEvent(); + Instant startTime = Instant.EPOCH; + String cause = "?"; + String name = "?"; + if (endEvent != null) { + name = getName(); + startTime = endEvent.getStartTime(); + cause = Events.assertField(endEvent, "cause").getValue(); + } + return String.format("GcEvent: gcId=%d, method=%s, cause=%s, startTime=%s", + getGcId(), name, cause, startTime); + } + + public String getLog() { + StringBuilder sb = new StringBuilder(); + sb.append(this.toString() + System.getProperty("line.separator")); + for (RecordedEvent event : events) { + sb.append(String.format("event: %s%n", event)); + } + return sb.toString(); + } + + // Group all events info batches. + public static List createFromEvents(List events) throws Exception { + Stack openGcIds = new Stack<>(); + List batches = new ArrayList<>(); + GcBatch currBatch = null; + + for (RecordedEvent event : events) { + if (!isGcEvent(event)) { + continue; + } + int gcId = GCHelper.getGcId(event); + if (currBatch == null || currBatch.getGcId() != gcId) { + currBatch = null; + // Search for existing batch + for (GcBatch loopBatch : batches) { + if (gcId == loopBatch.getGcId()) { + currBatch = loopBatch; + break; + } + } + if (currBatch == null) { + // No existing batch. Create new. + currBatch = new GcBatch(); + batches.add(currBatch); + openGcIds.push(new Integer(gcId)); + } + } + boolean isEndEvent = currBatch.addEvent(event); + if (isEndEvent) { + openGcIds.pop(); + } + } + // Verify that all start_garbage_collection events have received a corresponding "garbage_collection" event. + for (GcBatch batch : batches) { + if (batch.getEndEvent() == null) { + System.out.println(batch.getLog()); + } + assertNotNull(batch.getEndEvent(), "GcBatch has no end event"); + } + return batches; + } + } + + /** + * Contains number of collections and sum pause time for young and old collections. + */ + public static class CollectionSummary { + public long collectionCountOld; + public long collectionCountYoung; + public long collectionTimeOld; + public long collectionTimeYoung; + private Set names = new HashSet<>(); + + public void add(String collectorName, boolean isYoung, long count, long time) { + if (isYoung) { + collectionCountYoung += count; + collectionTimeYoung += time; + } else { + collectionCountOld += count; + collectionTimeOld += time; + } + if (!names.contains(collectorName)) { + names.add(collectorName); + } + } + + public long sum() { + return collectionCountOld + collectionCountYoung; + } + + public CollectionSummary calcDelta(CollectionSummary prev) { + CollectionSummary delta = new CollectionSummary(); + delta.collectionCountOld = this.collectionCountOld - prev.collectionCountOld; + delta.collectionTimeOld = this.collectionTimeOld - prev.collectionTimeOld; + delta.collectionCountYoung = this.collectionCountYoung - prev.collectionCountYoung; + delta.collectionTimeYoung = this.collectionTimeYoung - prev.collectionTimeYoung; + delta.names.addAll(this.names); + delta.names.addAll(prev.names); + return delta; + } + + public static CollectionSummary createFromMxBeans() { + CollectionSummary summary = new CollectionSummary(); + List gcBeans = ManagementFactory.getGarbageCollectorMXBeans(); + for (int c=0; c batches) { + CollectionSummary summary = new CollectionSummary(); + for (GcBatch batch : batches) { + RecordedEvent endEvent = batch.getEndEvent(); + assertNotNull(endEvent, "No end event in batch with gcId " + batch.getGcId()); + String name = batch.getName(); + summary.add(name, batch.isYoungCollection(), 1, Events.assertField(endEvent, "sumOfPauses").getValue()); + } + return summary; + } + + public String toString() { + StringBuilder collectorNames = new StringBuilder(); + for (String s : names) { + if (collectorNames.length() > 0) { + collectorNames.append(", "); + } + collectorNames.append(s); + } + return String.format("CollectionSummary: young.collections=%d, young.time=%d, old.collections=%d, old.time=%d, collectors=(%s)", + collectionCountYoung, collectionTimeYoung, collectionCountOld, collectionTimeOld, collectorNames); + } + } + + public static PrintStream getDefaultErrorLog() { + if (defaultErrorLog == null) { + try { + defaultErrorLog = new PrintStream(new FileOutputStream("error.log", true)); + } catch (IOException e) { + e.printStackTrace(); + defaultErrorLog = System.err; + } + } + return defaultErrorLog; + } + + public static void log(Object msg) { + log(msg, System.err); + log(msg, getDefaultErrorLog()); + } + + public static void log(Object msg, PrintStream ps) { + ps.println(msg); + } + + public static boolean isValidG1HeapRegionType(final String type) { + return g1HeapRegionTypes.contains(type); + } + + /** + * Helper function to align heap size up. + * + * @param value + * @param alignment + * @return aligned value + */ + public static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + /** + * Helper function to align heap size down. + * + * @param value + * @param alignment + * @return aligned value + */ + public static long alignDown(long value, long alignment) { + return value & ~(alignment - 1); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/RecurseThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/RecurseThread.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,93 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import jdk.test.lib.Asserts; + +public class RecurseThread extends Thread { + + public int totalDepth; + public long dummy = 0; // Just to make sure the optimizer does not remove the test code. + private volatile boolean timeToQuit = false; + private volatile boolean isInRunLoop = false; + + public RecurseThread(int totalDepth) { + this.totalDepth = totalDepth; + } + + @Override + public void run() { + // totalDepth includes functions run() and recurse() and runloop(). + // Remove 3 from totalDepth when recursing. + final int minDepth = 3; + Asserts.assertGreaterThanOrEqual(totalDepth, minDepth, "totalDepth too small"); + int recurseDepth = totalDepth - minDepth; + + // We want the last function before runloop() to be recurseA(). + boolean startWithRecurseA = (totalDepth % 2) != 0; + dummy = startWithRecurseA ? recurseA(recurseDepth) : recurseB(recurseDepth); + } + + public void quit() { + timeToQuit = true; + } + + public boolean isInRunLoop() { + return isInRunLoop; + } + + private long recurseA(int depth) { + if (depth == 0) { + return recurseEnd(); + } else { + return recurseB(depth - 1); + } + } + + private long recurseB(int depth) { + if (depth == 0) { + return recurseEnd(); + } else { + return recurseA(depth - 1); + } + } + + // Test expects this function to be at the top of the stack. + // We should not call other functions from here. + private long recurseEnd() { + isInRunLoop = true; + long[] dummyTable = new long[] { 0, 2, 4, 8, 16 }; + long dummyTotal = 0; + while (!timeToQuit) { + dummyTotal = 0; + for (int i = 0; i < 5; ++i) { + dummyTotal += dummyTable[i]; + } + } + return dummyTotal; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/SimpleEvent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/SimpleEvent.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,32 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import jdk.jfr.Event; + +public class SimpleEvent extends Event { + public int id; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/SimpleEventHelper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/SimpleEventHelper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,107 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.Asserts; + +public class SimpleEventHelper { + + public static void enable(Recording r, boolean isEnabled) { + if (isEnabled) { + r.enable(SimpleEvent.class).withThreshold(Duration.ofMillis(0)).withoutStackTrace(); + } else { + r.disable(SimpleEvent.class); + } + } + + public static SimpleEvent createEvent(int id) { + SimpleEvent event = new SimpleEvent(); + event.begin(); + event.id = id; + event.end(); + event.commit(); + return event; + } + + public static void verifyEvents(Recording r, int ... ids) throws Exception { + List eventIds = new ArrayList<>(); + for (RecordedEvent event : Events.fromRecording(r)) { + if (Events.isEventType(event, SimpleEvent.class.getName())) { + int id = Events.assertField(event, "id").getValue(); + System.out.printf("recording %s: event.id=%d%n", r.getName(), id); + eventIds.add(id); + } + } + Asserts.assertEquals(eventIds.size(), ids.length, "Wrong number of events"); + for (int i = 0; i < ids.length; ++i) { + Asserts.assertEquals(eventIds.get(i).intValue(), ids[i], "Wrong id in event"); + } + } + + public static void verifyContains(List events, int ... ids) throws Exception { + Set missingIds = new HashSet<>(); + for (int id : ids) { + missingIds.add(id); + } + for (RecordedEvent event : getSimpleEvents(events)) { + int id = Events.assertField(event, "id").getValue(); + System.out.printf("event.id=%d%n", id); + missingIds.remove(new Integer(id)); + } + if (!missingIds.isEmpty()) { + missingIds.forEach(id -> System.out.println("Missing MyEvent with id " + id)); + Asserts.fail("Missing some MyEvent events"); + } + } + + public static void verifyNotContains(List events, int ... ids) throws Exception { + for (RecordedEvent event : getSimpleEvents(events)) { + int eventId = Events.assertField(event, "id").getValue(); + System.out.printf("event.id=%d%n", eventId); + for (int id : ids) { + Events.assertField(event, "id").notEqual(id); + } + } + } + + public static List getSimpleEvents(List events) { + List myEvents = new ArrayList<>(); + for (RecordedEvent event : events) { + if (Events.isEventType(event, SimpleEvent.class.getName())) { + myEvents.add(event); + } + } + return myEvents; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/SimpleSetting.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/SimpleSetting.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,47 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import java.util.Set; + +import jdk.jfr.SettingControl; + +public class SimpleSetting extends SettingControl { + + @Override + public String combine(Set settingValue) { + return "none"; + } + + @Override + public void setValue(String value) { + } + + @Override + public String getValue() { + return "none"; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/Stressor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/Stressor.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,49 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.test.lib.jfr; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class to help run multiple threads executing some task + * + * + * @since 1.9 + */ +public class Stressor { + public static void execute(int numberOfThreads, Thread.UncaughtExceptionHandler eh, Runnable task) throws Exception { + List threads = new ArrayList<>(); + for (int n = 0; n < numberOfThreads; ++n) { + Thread t = new Thread(task); + t.setUncaughtExceptionHandler(eh); + threads.add(t); + t.start(); + } + for (Thread t : threads) { + t.join(); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/TestClassLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/TestClassLoader.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,77 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * Custom class loader which will try to load the class via getResourceAsStream(). + * If there are any errors, the parent class loader will be used instead. + */ +public class TestClassLoader extends ClassLoader { + static public final String CLASS_LOADER_NAME = "JFR TestClassLoader"; + + public TestClassLoader() { + super(CLASS_LOADER_NAME, ClassLoader.getSystemClassLoader()); + } + + public Class loadClass(String name) throws ClassNotFoundException { + + InputStream is = null; + DataInputStream dis = null; + try { + String resourceName = name.replace('.', '/') + ".class"; + is = getResourceAsStream(resourceName); + if (is != null) { + int i = is.available(); + byte buf[] = new byte[i]; + dis = new DataInputStream(is); + dis.readFully(buf); + dis.close(); + return defineClass(name, buf, 0, buf.length); + } + } catch (SecurityException e) { + // This error will happen quite often (for example when loading + // "java.lang..."). + // Ignore this error and use parent class loader. + } catch (IOException e) { + // Unexpected error. Use parent class loader. + e.printStackTrace(); + } finally { + if (dis != null) { + try { + dis.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return super.loadClass(name); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/jfr/VoidFunction.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/jfr/VoidFunction.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,31 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.jfr; + +@FunctionalInterface +public interface VoidFunction { + void run() throws Throwable; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/management/DynamicVMOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/management/DynamicVMOption.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.management; + +import com.sun.management.HotSpotDiagnosticMXBean; +import java.lang.management.ManagementFactory; + +/** + * A utility class to work with VM options which could be altered during + * execution. + * + * This class is a wrapper around {@code com.sun.management.VMOption}. + * It provides more convenient interface to read/write the values. + * + */ +public class DynamicVMOption { + + private final HotSpotDiagnosticMXBean mxBean; + + /** + * VM option name, like "MinHeapFreeRatio". + */ + public final String name; + + /** + * Creates an instance of DynamicVMOption. + * + * @param name the VM option name + */ + public DynamicVMOption(String name) { + this.name = name; + mxBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); + } + + /** + * Sets a new value for the option. + * Trying to set not applicable value will cause IllegalArgumentException. + * Behavior with null is undefined, most likely NPE will be thrown. + * + * @param newValue the value to be set + * @see #getValue() + * @throws IllegalArgumentException if newValue is not applicable to the option + */ + public final void setValue(String newValue) { + mxBean.setVMOption(name, newValue); + } + + /** + * Returns the value of option. + * + * @return the current option value + * @see #setValue(java.lang.String) + */ + public final String getValue() { + return mxBean.getVMOption(name).getValue(); + } + + /** + * Returns true, if option is writable, false otherwise. + * + * @return true, if option is writable, false otherwise + */ + public final boolean isWriteable() { + return mxBean.getVMOption(name).isWriteable(); + } + + /** + * Checks if the given value is applicable for the option. + * + * This method tries to set the option to the new value. If no exception + * has been thrown the value is treated as valid. + * + * Calling this method will not change the option value. After an attempt + * to set a new value, the option will be restored to its previous value. + * + * @param value the value to verify + * @return true if option could be set to the given value + */ + public boolean isValidValue(String value) { + boolean isValid = true; + String oldValue = getValue(); + try { + setValue(value); + } catch (NullPointerException e) { + if (value == null) { + isValid = false; + } + } catch (IllegalArgumentException e) { + isValid = false; + } finally { + setValue(oldValue); + } + return isValid; + } + + /** + * Returns the value of the given VM option as String. + * + * This is a simple shortcut for {@code new DynamicVMOption(name).getValue()} + * + * @param name the name of VM option + * @return value as a string + * @see #getValue() + */ + public static String getString(String name) { + return new DynamicVMOption(name).getValue(); + } + + /** + * Returns the value of the given option as int. + * + * @param name the name of VM option + * @return value parsed as integer + * @see #getString(java.lang.String) + * + */ + public static int getInt(String name) { + return Integer.parseInt(getString(name)); + } + + /** + * Sets the VM option to a new value. + * + * This is a simple shortcut for {@code new DynamicVMOption(name).setValue(value)} + * + * @param name the name of VM option + * @param value the value to be set + * @see #setValue(java.lang.String) + */ + public static void setString(String name, String value) { + new DynamicVMOption(name).setValue(value); + } + + /** + * Sets the VM option value to a new integer value. + * + * @param name the name of VM option + * @param value the integer value to be set + * @see #setString(java.lang.String, java.lang.String) + */ + public static void setInt(String name, int value) { + new DynamicVMOption(name).setValue(Integer.toString(value)); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/management/InputArguments.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/management/InputArguments.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.management; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.List; + +public class InputArguments { + /** + * Gets the array of strings containing input arguments passed to the VM + * + * @return arguments + */ + public static String[] getVmInputArgs() { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + List args = runtime.getInputArguments(); + return args.toArray(new String[args.size()]); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/management/ThreadMXBeanTool.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.management; + +import java.lang.management.ManagementFactory; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; + +/** + * A few utility methods to use ThreadMXBean. + */ +public final class ThreadMXBeanTool { + + /** + * Waits until {@link Thread} is in the certain {@link Thread.State} + * and blocking on {@code object}. + * + * @param state The thread state + * @param object The object to block on + */ + public static void waitUntilBlockingOnObject(Thread thread, Thread.State state, Object object) + throws InterruptedException { + String want = object == null ? null : object.getClass().getName() + '@' + + Integer.toHexString(System.identityHashCode(object)); + ThreadMXBean tmx = ManagementFactory.getThreadMXBean(); + while (thread.isAlive()) { + ThreadInfo ti = tmx.getThreadInfo(thread.getId()); + if (ti.getThreadState() == state + && (want == null || want.equals(ti.getLockName()))) { + return; + } + Thread.sleep(1); + } + } + + /** + * Waits until {@link Thread} is in native. + */ + public static void waitUntilInNative(Thread thread) throws InterruptedException { + ThreadMXBean tmx = ManagementFactory.getThreadMXBean(); + while (thread.isAlive()) { + ThreadInfo ti = tmx.getThreadInfo(thread.getId()); + if (ti.isInNative()) { + return; + } + Thread.sleep(1); + } + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/net/IPSupport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/net/IPSupport.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.net; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.concurrent.Callable; +import jtreg.SkippedException; + +/** + * Determines Internet Protocol version support at the TCP socket level. + */ +public class IPSupport { + + private static final boolean hasIPv4; + private static final boolean hasIPv6; + private static final boolean preferIPv4Stack; + + static { + try { + InetAddress loopbackIPv4 = InetAddress.getByAddress( + new byte[] {0x7F, 0x00, 0x00, 0x01}); + + InetAddress loopbackIPv6 = InetAddress.getByAddress( + new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}); + + hasIPv4 = runPrivilegedAction(() -> hasAddress(loopbackIPv4)); + hasIPv6 = runPrivilegedAction(() -> hasAddress(loopbackIPv6)); + } catch (UnknownHostException e) { + throw new AssertionError(e); + } + preferIPv4Stack = runPrivilegedAction(() -> Boolean.parseBoolean( + System.getProperty("java.net.preferIPv4Stack"))); + if (!preferIPv4Stack && !hasIPv4 && !hasIPv6) { + throw new AssertionError("IPv4 and IPv6 both not available and java.net.preferIPv4Stack is not true"); + } + } + + private static boolean hasAddress(InetAddress address) { + try (Socket socket = new Socket()) { + socket.bind(new InetSocketAddress(address, 0)); + return true; + } catch (SocketException se) { + return false; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private static T runPrivilegedAction(Callable callable) { + try { + PrivilegedExceptionAction pa = () -> callable.call(); + return AccessController.doPrivileged(pa); + } catch (PrivilegedActionException pae) { + throw new UncheckedIOException((IOException) pae.getCause()); + } + } + + private IPSupport() { } + + /** + * Whether or not IPv4 is supported. + */ + public static final boolean hasIPv4() { + return hasIPv4; + } + + /** + * Whether or not IPv6 is supported. + */ + public static final boolean hasIPv6() { + return hasIPv6; + } + + /** + * Whether or not the "java.net.preferIPv4Stack" system property is set. + */ + public static final boolean preferIPv4Stack() { + return preferIPv4Stack; + } + + + /** + * Whether or not the current networking configuration is valid or not. + * + * If preferIPv4Stack is true but there is no IPv4 support, the configuration is invalid. + */ + public static final boolean currentConfigurationIsValid() { + return hasIPv4() || hasIPv6(); + } + + /** + * Throws a jtreg.SkippedException if the current networking configuration is invalid. + */ + public static void skipIfCurrentConfigurationIsInvalid() throws SkippedException { + if (!currentConfigurationIsValid()) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(os); + ps.println("Invalid networking configuration"); + printPlatformSupport(ps); + throw new SkippedException(os.toString()); + } + } + + /** + * Prints the platform supported configurations. + */ + public static void printPlatformSupport(PrintStream out) { + out.println("IPSupport - IPv4: " + hasIPv4()); + out.println("IPSupport - IPv6: " + hasIPv6()); + out.println("preferIPv4Stack: " + preferIPv4Stack()); + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/net/SimpleSSLContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/net/SimpleSSLContext.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,128 @@ +/* + * 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 jdk.test.lib.net; + +import java.util.*; +import java.io.*; +import java.security.*; +import java.security.cert.*; +import javax.net.ssl.*; + +/** + * Creates a simple usable SSLContext for SSLSocketFactory + * or a HttpsServer using either a given keystore or a default + * one in the test tree. + * + * Using this class with a security manager requires the following + * permissions to be granted: + * + * permission "java.util.PropertyPermission" "test.src.path", "read"; + * permission java.io.FilePermission "/path/to/test/lib/jdk/test/lib/testkeys", "read"; + * The exact path above depends on the location of the test. + */ +public class SimpleSSLContext { + + SSLContext ssl; + + /** + * loads default keystore from SimpleSSLContext + * source directory + */ + public SimpleSSLContext() throws IOException { + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override + public Void run() throws Exception { + String paths = System.getProperty("test.src.path"); + StringTokenizer st = new StringTokenizer(paths, File.pathSeparator); + boolean securityExceptions = false; + while (st.hasMoreTokens()) { + String path = st.nextToken(); + try { + File f = new File(path, "jdk/test/lib/net/testkeys"); + if (f.exists()) { + try (FileInputStream fis = new FileInputStream(f)) { + init(fis); + return null; + } + } + } catch (SecurityException e) { + // catch and ignore because permission only required + // for one entry on path (at most) + securityExceptions = true; + } + } + if (securityExceptions) { + System.err.println("SecurityExceptions thrown on loading testkeys"); + } + return null; + } + }); + } catch (PrivilegedActionException pae) { + Throwable t = pae.getCause() != null ? pae.getCause() : pae; + if (t instanceof IOException) + throw (IOException)t; + if (t instanceof RuntimeException) + throw (RuntimeException)t; + if (t instanceof Error) + throw (Error)t; + throw new RuntimeException(t); + } + } + + /** + * loads default keystore from given directory + */ + public SimpleSSLContext(String dir) throws IOException { + String file = dir + "/testkeys"; + try (FileInputStream fis = new FileInputStream(file)) { + init(fis); + } + } + + private void init(InputStream i) throws IOException { + try { + char[] passphrase = "passphrase".toCharArray(); + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(i, passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(ks); + + ssl = SSLContext.getInstance("TLS"); + ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } catch (KeyManagementException | KeyStoreException | + UnrecoverableKeyException | CertificateException | + NoSuchAlgorithmException e) { + throw new RuntimeException(e.getMessage()); + } + } + + public SSLContext get() { + return ssl; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/net/URIBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/net/URIBuilder.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, Google and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.net; + +import java.net.InetAddress; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +public class URIBuilder { + + public static URIBuilder newBuilder() { + return new URIBuilder(); + } + + private String scheme; + private String userInfo; + private String host; + private int port; + private String path; + private String query; + private String fragment; + + private URIBuilder() {} + + public URIBuilder scheme(String scheme) { + this.scheme = scheme; + return this; + } + + public URIBuilder userInfo(String userInfo) { + this.userInfo = userInfo; + return this; + } + + public URIBuilder host(String host) { + this.host = host; + return this; + } + + public URIBuilder host(InetAddress address) { + String hostaddr = address.isAnyLocalAddress() + ? "localhost" : address.getHostAddress(); + return host(hostaddr); + } + + public URIBuilder loopback() { + return host(InetAddress.getLoopbackAddress().getHostAddress()); + } + + public URIBuilder port(int port) { + this.port = port; + return this; + } + + public URIBuilder path(String path) { + this.path = path; + return this; + } + + public URIBuilder query(String query) { + this.query = query; + return this; + } + + public URIBuilder fragment(String fragment) { + this.fragment = fragment; + return this; + } + + public URI build() throws URISyntaxException { + return new URI(scheme, userInfo, host, port, path, query, fragment); + } + + public URI buildUnchecked() { + try { + return build(); + } catch (URISyntaxException e) { + throw new IllegalArgumentException(e); + } + } + + public URL toURL() throws URISyntaxException, MalformedURLException { + return build().toURL(); + } + + public URL toURLUnchecked() { + try { + return toURL(); + } catch (URISyntaxException | MalformedURLException e) { + throw new IllegalArgumentException(e); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/process/ExitCode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/process/ExitCode.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.process; + +/** + * Exit code values that could be returned by the JVM. + */ +public enum ExitCode { + OK(0), + FAIL(1), + CRASH(134); + + public final int value; + + ExitCode(int value) { + this.value = value; + } +} + diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/process/OutputAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/process/OutputAnalyzer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,701 @@ +/* + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.process; + +import jdk.test.lib.Asserts; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class OutputAnalyzer { + + private final OutputBuffer buffer; + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process Process to analyze + * @throws IOException If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + buffer = OutputBuffer.of(process); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf String buffer to analyze + */ + public OutputAnalyzer(String buf) { + buffer = OutputBuffer.of(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param file File to analyze + */ + public OutputAnalyzer(Path file) throws IOException { + this(new String(Files.readAllBytes(file))); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout stdout buffer to analyze + * @param stderr stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + buffer = OutputBuffer.of(stdout, stderr); + } + + /** + * Verify that the stdout contents of output buffer is empty + * + * @throws RuntimeException + * If stdout was not empty + */ + public OutputAnalyzer stdoutShouldBeEmpty() { + if (!getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was not empty"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer is empty + * + * @throws RuntimeException + * If stderr was not empty + */ + public OutputAnalyzer stderrShouldBeEmpty() { + if (!getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer is empty, + * after filtering out the Hotspot warning messages + * + * @throws RuntimeException + * If stderr was not empty + */ + public OutputAnalyzer stderrShouldBeEmptyIgnoreVMWarnings() { + if (!getStderr().replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer is not empty + * + * @throws RuntimeException + * If stdout was empty + */ + public OutputAnalyzer stdoutShouldNotBeEmpty() { + if (getStdout().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was empty"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer is not empty + * + * @throws RuntimeException + * If stderr was empty + */ + public OutputAnalyzer stderrShouldNotBeEmpty() { + if (getStderr().isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was empty"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public OutputAnalyzer shouldContain(String expectedString) { + String stdout = getStdout(); + String stderr = getStderr(); + if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public OutputAnalyzer stdoutShouldContain(String expectedString) { + String stdout = getStdout(); + if (!stdout.contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public OutputAnalyzer stderrShouldContain(String expectedString) { + String stderr = getStderr(); + if (!stderr.contains(expectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + expectedString + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not contain the string + * + * @param notExpectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public OutputAnalyzer shouldNotContain(String notExpectedString) { + String stdout = getStdout(); + String stderr = getStderr(); + if (stdout.contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); + } + if (stderr.contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer are empty + * + * @throws RuntimeException If the stdout and stderr are not empty + */ + public OutputAnalyzer shouldBeEmpty() { + String stdout = getStdout(); + String stderr = getStderr(); + if (!stdout.isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was not empty"); + } + if (!stderr.isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer does not contain the string + * + * @param notExpectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) { + String stdout = getStdout(); + if (stdout.contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not contain the string + * + * @param notExpectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public OutputAnalyzer stderrShouldNotContain(String notExpectedString) { + String stderr = getStderr(); + if (stderr.contains(notExpectedString)) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + notExpectedString + "' found in stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer matches + * the pattern + * + * @param regexp + * @throws RuntimeException If the pattern was not found + */ + public OutputAnalyzer shouldMatch(String regexp) { + String stdout = getStdout(); + String stderr = getStderr(); + Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE); + Matcher stdoutMatcher = pattern.matcher(stdout); + Matcher stderrMatcher = pattern.matcher(stderr); + if (!stdoutMatcher.find() && !stderrMatcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' missing from stdout/stderr \n"); + } + return this; + } + + /** + * Verify that the stdout contents of output buffer matches the + * pattern + * + * @param regexp + * @throws RuntimeException If the pattern was not found + */ + public OutputAnalyzer stdoutShouldMatch(String regexp) { + String stdout = getStdout(); + Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stdout); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' missing from stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer matches the + * pattern + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public OutputAnalyzer stderrShouldMatch(String pattern) { + String stderr = getStderr(); + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stderr \n"); + } + return this; + } + + /** + * Verify that the stdout and stderr contents of output buffer does not + * match the pattern + * + * @param regexp + * @throws RuntimeException If the pattern was found + */ + public OutputAnalyzer shouldNotMatch(String regexp) { + String stdout = getStdout(); + Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE); + Matcher matcher = pattern.matcher(stdout); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' found in stdout: '" + matcher.group() + "' \n"); + } + + String stderr = getStderr(); + matcher = pattern.matcher(stderr); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' found in stderr: '" + matcher.group() + "' \n"); + } + + return this; + } + + /** + * Verify that the stdout contents of output buffer does not match the + * pattern + * + * @param regexp + * @throws RuntimeException If the pattern was found + */ + public OutputAnalyzer stdoutShouldNotMatch(String regexp) { + String stdout = getStdout(); + Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stdout); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' found in stdout \n"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer does not match the + * pattern + * + * @param regexp + * @throws RuntimeException If the pattern was found + */ + public OutputAnalyzer stderrShouldNotMatch(String regexp) { + String stderr = getStderr(); + Matcher matcher = Pattern.compile(regexp, Pattern.MULTILINE).matcher(stderr); + if (matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + regexp + + "' found in stderr \n"); + } + return this; + } + + /** + * Get the captured group of the first string matching the pattern. + * stderr is searched before stdout. + * + * @param regexp The multi-line pattern to match + * @param group The group to capture + * @return The matched string or null if no match was found + */ + public String firstMatch(String regexp, int group) { + Pattern pattern = Pattern.compile(regexp, Pattern.MULTILINE); + String stderr = getStderr(); + Matcher stderrMatcher = pattern.matcher(stderr); + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + String stdout = getStdout(); + Matcher stdoutMatcher = pattern.matcher(stdout); + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. + * stderr is searched before stdout. + * + * @param pattern The multi-line pattern to match + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern) { + return firstMatch(pattern, 0); + } + + /** + * Verify the exit value of the process + * + * @param expectedExitValue Expected exit value from process + * @throws RuntimeException If the exit value from the process did not match the expected value + */ + public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Expected to get exit value of [" + + expectedExitValue + "]\n"); + } + return this; + } + + /** + * Verify the exit value of the process + * + * @param notExpectedExitValue Unexpected exit value from process + * @throws RuntimeException If the exit value from the process did match the expected value + */ + public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) { + if (getExitValue() == notExpectedExitValue) { + reportDiagnosticSummary(); + throw new RuntimeException("Unexpected to get exit value of [" + + notExpectedExitValue + "]\n"); + } + return this; + } + + + /** + * Report summary that will help to diagnose the problem + * Currently includes: + * - standard input produced by the process under test + * - standard output + * - exit code + * Note: the command line is printed by the ProcessTools + */ + public void reportDiagnosticSummary() { + String msg = + " stdout: [" + getStdout() + "];\n" + + " stderr: [" + getStderr() + "]\n" + + " exitValue = " + getExitValue() + "\n"; + + System.err.println(msg); + } + + /** + * Print the stdout buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer outputTo(PrintStream out) { + out.println(getStdout()); + return this; + } + + /** + * Print the stderr buffer to the given {@code PrintStream}. + * + * @return this OutputAnalyzer + */ + public OutputAnalyzer errorTo(PrintStream out) { + out.println(getStderr()); + return this; + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return getStdout() + getStderr(); + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return buffer.getStdout(); + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return buffer.getStderr(); + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return buffer.getExitValue(); + } + + /** + * Get the contents of the output buffer (stdout and stderr) as list of strings. + * Output will be split by newlines. + * + * @return Contents of the output buffer as list of strings + */ + public List asLines() { + return asLines(getOutput()); + } + + private List asLines(String buffer) { + return Arrays.asList(buffer.split("\\R")); + } + + + private static final String jvmwarningmsg = ".* VM warning:.*"; + + /** + * Verifies that the stdout and stderr contents of output buffer are empty, after + * filtering out the HotSpot warning messages. + * + * @throws RuntimeException If the stdout and stderr are not empty + */ + public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() { + String stdout = getStdout(); + String stderr = getStderr(); + if (!stdout.isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stdout was not empty"); + } + if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) { + reportDiagnosticSummary(); + throw new RuntimeException("stderr was not empty"); + } + return this; + } + + /** + * Verify that the stderr contents of output buffer matches the pattern, + * after filtering out the Hotespot warning messages + * + * @param pattern + * @throws RuntimeException If the pattern was not found + */ + public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) { + String stderr = getStderr().replaceAll(jvmwarningmsg + "\\R", ""); + Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + if (!matcher.find()) { + reportDiagnosticSummary(); + throw new RuntimeException("'" + pattern + + "' missing from stderr \n"); + } + return this; + } + + /** + * Returns the contents of the output buffer (stdout and stderr), without those + * JVM warning msgs, as list of strings. Output is split by newlines. + * + * @return Contents of the output buffer as list of strings + */ + public List asLinesWithoutVMWarnings() { + return Arrays.stream(getOutput().split("\\R")) + .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate()) + .collect(Collectors.toList()); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public OutputAnalyzer shouldMatchByLine(String pattern) { + return shouldMatchByLine(null, null, pattern); + } + + /** + * @see #stdoutShouldMatchByLine(String, String, String) + */ + public OutputAnalyzer stdoutShouldMatchByLine(String pattern) { + return stdoutShouldMatchByLine(null, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public OutputAnalyzer shouldMatchByLineFrom(String from, String pattern) { + return shouldMatchByLine(from, null, pattern); + } + + /** + * @see #shouldMatchByLine(String, String, String) + */ + public OutputAnalyzer shouldMatchByLineTo(String to, String pattern) { + return shouldMatchByLine(null, to, pattern); + } + + /** + * Verify that the stdout and stderr contents of output buffer match the + * {@code pattern} line by line. The whole output could be matched or + * just a subset of it. + * + * @param from + * The line from where output will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where output will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + */ + public OutputAnalyzer shouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getOutput(), from, to, pattern); + } + + /** + * Verify that the stdout contents of output buffer matches the + * {@code pattern} line by line. The whole stdout could be matched or + * just a subset of it. + * + * @param from + * The line from where stdout will be matched. + * Set {@code from} to null for matching from the first line. + * @param to + * The line until where stdout will be matched. + * Set {@code to} to null for matching until the last line. + * @param pattern + * Matching pattern + */ + public OutputAnalyzer stdoutShouldMatchByLine(String from, String to, String pattern) { + return shouldMatchByLine(getStdout(), from, to, pattern); + } + + private OutputAnalyzer shouldMatchByLine(String buffer, String from, String to, String pattern) { + List lines = asLines(buffer); + + int fromIndex = 0; + if (from != null) { + fromIndex = indexOf(lines, from); + Asserts.assertGreaterThan(fromIndex, -1, + "The line/pattern '" + from + "' from where the output should match can not be found"); + } + + int toIndex = lines.size(); + if (to != null) { + toIndex = indexOf(lines, to); + Asserts.assertGreaterThan(toIndex, -1, + "The line/pattern '" + to + "' until where the output should match can not be found"); + } + + List subList = lines.subList(fromIndex, toIndex); + Asserts.assertFalse(subList.isEmpty(), "There are no lines to check"); + + subList.stream() + .filter(Pattern.compile(pattern).asPredicate().negate()) + .findAny() + .ifPresent(line -> Asserts.assertTrue(false, + "The line '" + line + "' does not match pattern '" + pattern + "'")); + + return this; + } + + /** + * Check if there is a line matching {@code regexp} and return its index + * + * @param regexp Matching pattern + * @return Index of first matching line + */ + private int indexOf(List lines, String regexp) { + Pattern pattern = Pattern.compile(regexp); + for (int i = 0; i < lines.size(); i++) { + if (pattern.matcher(lines.get(i)).matches()) { + return i; + } + } + return -1; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/process/OutputBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/process/OutputBuffer.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,147 @@ +/* + * 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 jdk.test.lib.process; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public interface OutputBuffer { + public static class OutputBufferException extends RuntimeException { + private static final long serialVersionUID = 8528687792643129571L; + + public OutputBufferException(Throwable cause) { + super(cause); + } + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout(); + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr(); + public int getExitValue(); + + public static OutputBuffer of(Process p) { + return new LazyOutputBuffer(p); + } + + public static OutputBuffer of(String stdout, String stderr, int exitValue) { + return new EagerOutputBuffer(stdout, stderr, exitValue); + } + + public static OutputBuffer of(String stdout, String stderr) { + return of(stdout, stderr, -1); + } + + class LazyOutputBuffer implements OutputBuffer { + private static class StreamTask { + private final ByteArrayOutputStream buffer; + private final Future future; + + private StreamTask(InputStream stream) { + this.buffer = new ByteArrayOutputStream(); + this.future = new StreamPumper(stream, buffer).process(); + } + + public String get() { + try { + future.get(); + return buffer.toString(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } catch (ExecutionException | CancellationException e) { + throw new OutputBufferException(e); + } + } + } + + private final StreamTask outTask; + private final StreamTask errTask; + private final Process p; + + private LazyOutputBuffer(Process p) { + this.p = p; + outTask = new StreamTask(p.getInputStream()); + errTask = new StreamTask(p.getErrorStream()); + } + + @Override + public String getStdout() { + return outTask.get(); + } + + @Override + public String getStderr() { + return errTask.get(); + } + + @Override + public int getExitValue() { + try { + return p.waitFor(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new OutputBufferException(e); + } + } + } + + class EagerOutputBuffer implements OutputBuffer { + private final String stdout; + private final String stderr; + private final int exitValue; + + private EagerOutputBuffer(String stdout, String stderr, int exitValue) { + this.stdout = stdout; + this.stderr = stderr; + this.exitValue = exitValue; + } + + @Override + public String getStdout() { + return stdout; + } + + @Override + public String getStderr() { + return stderr; + } + + @Override + public int getExitValue() { + return exitValue; + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/process/ProcessTools.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/process/ProcessTools.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,567 @@ +/* + * 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 jdk.test.lib.process; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.concurrent.CountDownLatch; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.function.Predicate; +import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Utils; + +import vm.share.ProcessUtils; + +public final class ProcessTools { + private static final class LineForwarder extends StreamPumper.LinePump { + private final PrintStream ps; + private final String prefix; + LineForwarder(String prefix, PrintStream os) { + this.ps = os; + this.prefix = prefix; + } + @Override + protected void processLine(String line) { + ps.println("[" + prefix + "] " + line); + } + } + + private ProcessTools() { + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + * @param name The process name + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder) + throws IOException { + return startProcess(name, processBuilder, (Consumer)null); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

It is possible to monitor the in-streams via the provided {@code consumer} + * @param name The process name + * @param consumer {@linkplain Consumer} instance to process the in-streams + * @param processBuilder The process builder + * @return Returns the initialized process + * @throws IOException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + Consumer consumer) + throws IOException { + try { + return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS); + } catch (InterruptedException | TimeoutException e) { + // will never happen + throw new RuntimeException(e); + } + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT + *

+ * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, null, linePredicate, timeout, unit); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT and monitor the + * in-streams via the provided {@linkplain Consumer} + *

+ * @param name The process name + * @param processBuilder The process builder + * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever + * @param unit The timeout {@linkplain TimeUnit} + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Consumer lineConsumer, + final Predicate linePredicate, + long timeout, + TimeUnit unit) + throws IOException, InterruptedException, TimeoutException { + System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" "))); + Process p = privilegedStart(processBuilder); + StreamPumper stdout = new StreamPumper(p.getInputStream()); + StreamPumper stderr = new StreamPumper(p.getErrorStream()); + + stdout.addPump(new LineForwarder(name, System.out)); + stderr.addPump(new LineForwarder(name, System.err)); + if (lineConsumer != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + lineConsumer.accept(line); + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } + + + CountDownLatch latch = new CountDownLatch(1); + if (linePredicate != null) { + StreamPumper.LinePump pump = new StreamPumper.LinePump() { + @Override + protected void processLine(String line) { + if (latch.getCount() > 0 && linePredicate.test(line)) { + latch.countDown(); + } + } + }; + stdout.addPump(pump); + stderr.addPump(pump); + } else { + latch.countDown(); + } + final Future stdoutTask = stdout.process(); + final Future stderrTask = stderr.process(); + + try { + if (timeout > -1) { + if (timeout == 0) { + latch.await(); + } else { + if (!latch.await(Utils.adjustTimeout(timeout), unit)) { + throw new TimeoutException(); + } + } + } + } catch (TimeoutException | InterruptedException e) { + System.err.println("Failed to start a process (thread dump follows)"); + for(Map.Entry s : Thread.getAllStackTraces().entrySet()) { + printStack(s.getKey(), s.getValue()); + } + + if (p.isAlive()) { + p.destroyForcibly(); + } + + stdoutTask.cancel(true); + stderrTask.cancel(true); + throw e; + } + + return new ProcessImpl(p, stdoutTask, stderrTask); + } + + /** + *

Starts a process from its builder.

+ * The default redirects of STDOUT and STDERR are started + *

+ * It is possible to wait for the process to get to a warmed-up state + * via {@linkplain Predicate} condition on the STDOUT. The warm-up will + * wait indefinitely. + *

+ * @param name The process name + * @param processBuilder The process builder + * @param linePredicate The {@linkplain Predicate} to use on the STDOUT + * Used to determine the moment the target app is + * properly warmed-up. + * It can be null - in that case the warmup is skipped. + * @return Returns the initialized {@linkplain Process} + * @throws IOException + * @throws InterruptedException + * @throws TimeoutException + */ + @SuppressWarnings("overloads") + public static Process startProcess(String name, + ProcessBuilder processBuilder, + final Predicate linePredicate) + throws IOException, InterruptedException, TimeoutException { + return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + return ProcessUtils.getPid(); + } + + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested and + * with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) { + return createJavaProcessBuilder(false, command); + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested, + * and with any platform specific arguments prepended. + * + * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts + * to the java arguments. + * @param command Arguments to pass to the java command. + * @return The ProcessBuilder instance representing the java command. + */ + public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + + args.add("-cp"); + args.add(System.getProperty("java.class.path")); + + if (addTestVmAndJavaOptions) { + Collections.addAll(args, Utils.getTestJavaOpts()); + } + + Collections.addAll(args, command); + + // Reporting + StringBuilder cmdLine = new StringBuilder(); + for (String cmd : args) + cmdLine.append(cmd).append(' '); + System.out.println("Command line: [" + cmdLine.toString() + "]"); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + } + + private static void printStack(Thread t, StackTraceElement[] stack) { + System.out.println("\t" + t + + " stack: (length = " + stack.length + ")"); + if (t != null) { + for (StackTraceElement stack1 : stack) { + System.out.println("\t" + stack1); + } + System.out.println(); + } + } + + /** + * Executes a test jvm process, waits for it to finish and returns the process output. + * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added. + * The java from the test.jdk is used to execute the command. + * + * The command line will be like: + * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds + * + * The jvm process will have exited before this method returns. + * + * @param cmds User specified arguments. + * @return The output from the process. + */ + public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception { + ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds)); + return executeProcess(pb); + } + + /** + * @see #executeTestJvm(String...) + * @param cmds User specified arguments. + * @return The output from the process. + */ + public static OutputAnalyzer executeTestJava(String... cmds) throws Exception { + return executeTestJvm(cmds); + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * The process will have exited before this method returns. + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception { + return executeProcess(pb, null); + } + + /** + * Executes a process, pipe some text into its STDIN, waits for it + * to finish and returns the process output. The process will have exited + * before this method returns. + * @param pb The ProcessBuilder to execute. + * @param input The text to pipe into STDIN. Can be null. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeProcess(ProcessBuilder pb, String input) throws Exception { + OutputAnalyzer output = null; + Process p = null; + boolean failed = false; + try { + p = privilegedStart(pb); + if (input != null) { + try (PrintStream ps = new PrintStream(p.getOutputStream())) { + ps.print(input); + } + } + + output = new OutputAnalyzer(p); + p.waitFor(); + + return output; + } catch (Throwable t) { + if (p != null) { + p.destroyForcibly().waitFor(); + } + + failed = true; + System.out.println("executeProcess() failed: " + t); + throw t; + } finally { + if (failed) { + System.err.println(getProcessLog(pb, output)); + } + } + } + + /** + * Executes a process, waits for it to finish and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The output from the process. + */ + public static OutputAnalyzer executeProcess(String... cmds) throws Throwable { + return executeProcess(new ProcessBuilder(cmds)); + } + + /** + * Used to log command line, stdout, stderr and exit code from an executed process. + * @param pb The executed process. + * @param output The output from the process. + */ + public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) { + String stderr = output == null ? "null" : output.getStderr(); + String stdout = output == null ? "null" : output.getStdout(); + String exitValue = output == null ? "null": Integer.toString(output.getExitValue()); + StringBuilder logMsg = new StringBuilder(); + final String nl = System.getProperty("line.separator"); + logMsg.append("--- ProcessLog ---" + nl); + logMsg.append("cmd: " + getCommandLine(pb) + nl); + logMsg.append("exitvalue: " + exitValue + nl); + logMsg.append("stderr: " + stderr + nl); + logMsg.append("stdout: " + stdout + nl); + + return logMsg.toString(); + } + + /** + * @return The full command line for the ProcessBuilder. + */ + public static String getCommandLine(ProcessBuilder pb) { + if (pb == null) { + return "null"; + } + StringBuilder cmd = new StringBuilder(); + for (String s : pb.command()) { + cmd.append(s).append(" "); + } + return cmd.toString().trim(); + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout, and returns the process output. + * + * The process will have exited before this method returns. + * + * @param cmds The command line to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(String... cmds) + throws Throwable { + String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + /** + * Executes a process, waits for it to finish, prints the process output + * to stdout and returns the process output. + * + * The process will have exited before this method returns. + * + * @param pb The ProcessBuilder to execute. + * @return The {@linkplain OutputAnalyzer} instance wrapping the process. + */ + public static OutputAnalyzer executeCommand(ProcessBuilder pb) + throws Throwable { + String cmdLine = pb.command().stream() + .map(x -> (x.contains(" ") || x.contains("$")) + ? ("'" + x + "'") : x) + .collect(Collectors.joining(" ")); + System.out.println("Command line: [" + cmdLine + "]"); + OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); + System.out.println(analyzer.getOutput()); + return analyzer; + } + + private static Process privilegedStart(ProcessBuilder pb) throws IOException { + try { + return AccessController.doPrivileged( + (PrivilegedExceptionAction) () -> pb.start()); + } catch (PrivilegedActionException e) { + @SuppressWarnings("unchecked") + IOException t = (IOException) e.getException(); + throw t; + } + } + + private static class ProcessImpl extends Process { + + private final Process p; + private final Future stdoutTask; + private final Future stderrTask; + + public ProcessImpl(Process p, Future stdoutTask, Future stderrTask) { + this.p = p; + this.stdoutTask = stdoutTask; + this.stderrTask = stderrTask; + } + + @Override + public OutputStream getOutputStream() { + return p.getOutputStream(); + } + + @Override + public InputStream getInputStream() { + return p.getInputStream(); + } + + @Override + public InputStream getErrorStream() { + return p.getErrorStream(); + } + + @Override + public int waitFor() throws InterruptedException { + int rslt = p.waitFor(); + waitForStreams(); + return rslt; + } + + @Override + public int exitValue() { + return p.exitValue(); + } + + @Override + public void destroy() { + p.destroy(); + } + + public long pid() { + return ProcessUtils.getPid(p); + } + + @Override + public boolean isAlive() { + return p.isAlive(); + } + + @Override + public Process destroyForcibly() { + return p.destroyForcibly(); + } + + @Override + public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { + boolean rslt = p.waitFor(timeout, unit); + if (rslt) { + waitForStreams(); + } + return rslt; + } + + private void waitForStreams() throws InterruptedException { + try { + stdoutTask.get(); + } catch (ExecutionException e) { + } + try { + stderrTask.get(); + } catch (ExecutionException e) { + } + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/process/StreamPumper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/process/StreamPumper.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.process; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.atomic.AtomicBoolean; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + /** + * Pump will be called by the StreamPumper to process the incoming data + */ + public abstract static class Pump { + abstract void register(StreamPumper d); + } + + /** + * OutputStream -> Pump adapter + */ + public final static class StreamPump extends Pump { + private final OutputStream out; + public StreamPump(OutputStream out) { + this.out = out; + } + + @Override + void register(StreamPumper sp) { + sp.addOutputStream(out); + } + } + + /** + * Used to process the incoming data line-by-line + */ + public abstract static class LinePump extends Pump { + @Override + final void register(StreamPumper sp) { + sp.addLineProcessor(this); + } + + protected abstract void processLine(String line); + } + + private final InputStream in; + private final Set outStreams = new HashSet<>(); + private final Set linePumps = new HashSet<>(); + + private final AtomicBoolean processing = new AtomicBoolean(false); + + public StreamPumper(InputStream in) { + this.in = in; + } + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in The stream to read from. + * @param out The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this(in); + this.addOutputStream(out); + } + + /** + * Implements Thread.run(). Continuously read from {@code in} and write to + * {@code out} until {@code in} has reached end of stream. Abort on + * interruption. Abort on IOExceptions. + */ + @Override + public void run() { + try (BufferedInputStream is = new BufferedInputStream(in)) { + ByteArrayOutputStream lineBos = new ByteArrayOutputStream(); + byte[] buf = new byte[BUF_SIZE]; + int len = 0; + int linelen = 0; + + while ((len = is.read(buf)) > 0 && !Thread.interrupted()) { + for (OutputStream out : outStreams) { + out.write(buf, 0, len); + } + if (!linePumps.isEmpty()) { + int i = 0; + int lastcrlf = -1; + while (i < len) { + if (buf[i] == '\n' || buf[i] == '\r') { + int bufLinelen = i - lastcrlf - 1; + if (bufLinelen > 0) { + lineBos.write(buf, lastcrlf + 1, bufLinelen); + } + linelen += bufLinelen; + + if (linelen > 0) { + lineBos.flush(); + final String line = lineBos.toString(); + linePumps.forEach((lp) -> lp.processLine(line)); + lineBos.reset(); + linelen = 0; + } + lastcrlf = i; + } + + i++; + } + if (lastcrlf == -1) { + lineBos.write(buf, 0, len); + linelen += len; + } else if (lastcrlf < len - 1) { + lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1); + linelen += len - lastcrlf - 1; + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } finally { + for (OutputStream out : outStreams) { + try { + out.flush(); + } catch (IOException e) {} + } + try { + in.close(); + } catch (IOException e) {} + } + } + + final void addOutputStream(OutputStream out) { + outStreams.add(out); + } + + final void addLineProcessor(LinePump lp) { + linePumps.add(lp); + } + + public final StreamPumper addPump(Pump ... pump) { + if (processing.get()) { + throw new IllegalStateException("Can not modify pumper while " + + "processing is in progress"); + } + for (Pump p : pump) { + p.register(this); + } + return this; + } + + public final Future process() { + if (!processing.compareAndSet(false, true)) { + throw new IllegalStateException("Can not re-run the processing"); + } + FutureTask result = new FutureTask<>(this, null); + Thread t = new Thread(result); + t.setDaemon(true); + t.start(); + + return result; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/DerUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/DerUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,117 @@ +/* + * 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 jdk.test.lib.security; + +import jdk.test.lib.Asserts; +import sun.security.util.DerInputStream; +import sun.security.util.DerValue; +import sun.security.util.ObjectIdentifier; + +import java.io.IOException; + +public class DerUtils { + /** + * Returns a DerValue (deep) inside another DerValue. + *

+ * The location of the inner DerValue is expressed as a string, in which + * each character is a step from the outer DerValue into the inner one. + * If it's a number n, the n'th element (starting from 0) of a sequence + * is the next step. If it's 'c', the content of an OctetString parsed + * as a DerValue is the next step. Note that n cannot be bigger than 9. + *

+ * Attention: do not reuse the return value. DerValue is mutable and + * reading it advances a pointer inside. + *

+ * For example, here is a PKCS #12 file: + *

+     * 0000:0845  [] SEQUENCE
+     * 0004:0003  [0]     INTEGER 3
+     * 0007:07FE  [1]     SEQUENCE
+     * 000B:000B  [10]         OID 1.2.840.113549.1.7.1 (data)
+     * 0016:07EF  [11]         cont [0]
+     * 001A:07EB  [110]             OCTET STRING
+     * ...
+     * 
+ * and the content of OCTET string at offset 001A can be parsed as another + * DerValue which is: + *
+     * 0000:07E7  [] SEQUENCE
+     * 0004:0303  [0]     SEQUENCE
+     * 0008:000B  [00]         OID 1.2.840.113549.1.7.1 (data)
+     * ....
+     * 
+ * Then the OID is {@code innerDerValue(data, "110c00").getOID()}. + * + * @param data the outer DerValue. We choose byte[] instead of DerValue + * because DerValue is mutable and cannot be reused. + * @param location the location of the inner DerValue + * @return the inner DerValue, or null if no DerValue is at the location + * @throws IOException if an I/O error happens + */ + public static DerValue innerDerValue(byte[] data, String location) + throws IOException { + + DerValue v = new DerValue(data); + for (char step : location.toCharArray()) { + if (step == 'c') { + v = new DerValue(v.getOctetString()); + } else { + DerInputStream ins = v.getData(); + // skip n DerValue in the sequence + for (int i = 0; i < step - '0'; i++) { + ins.getDerValue(); + } + if (ins.available() > 0) { + v = ins.getDerValue(); + } else { + return null; + } + } + } + return v; + } + + /** + * Ensures that the inner DerValue is the expected ObjectIdentifier. + */ + public static void checkAlg(byte[] der, String location, + ObjectIdentifier expected) throws Exception { + Asserts.assertEQ(innerDerValue(der, location).getOID(), expected); + } + + /** + * Ensures that the inner DerValue is the expected integer. + */ + public static void checkInt(byte[] der, String location, int expected) + throws Exception { + Asserts.assertEQ(innerDerValue(der, location).getInteger(), expected); + } + + /** + * Ensures that there is no inner DerValue at the specified location. + */ + public static void shouldNotExist(byte[] der, String location) + throws Exception { + Asserts.assertTrue(innerDerValue(der, location) == null); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/JDKSecurityProperties.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/JDKSecurityProperties.java Fri Sep 06 18:21:51 2019 +0300 @@ -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 jdk.test.lib.security; + +import java.util.List; +import java.security.Security; + +public final class JDKSecurityProperties { + + public static final List jdkProps = List.of( + "com.sun.CORBA.ORBIorTypeCheckRegistryFilter", + "crypto.policy", + "jceks.key.serialFilter", + "jdk.certpath.disabledAlgorithms", + "keystore.type", + "krb5.kdc.bad.policy", + "login.config", + "networkaddress.cache.ttl", + "ocsp.responderURL", + "package.access", + "policy.allowSystemProperty", + "securerandom.drbg.config", + "security.provider.1", + "ssl.KeyManagerFactory.algorithm", + "sun.rmi.registry.registryFilter" + ); + + public static List getKeys() { + return jdkProps; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/SSLSocketTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/SSLSocketTest.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,891 @@ +/* + * 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 jdk.test.lib.security; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManagerFactory; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.KeyFactory; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Base64; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * Template to help speed up your client/server tests. + * + * Two examples that use this template: + * test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java + * test/sun/net/www/protocol/https/HttpsClient/ServerIdentityTest.java + */ +public abstract class SSLSocketTest { + + /* + * Run the test case. + */ + public void run() throws Exception { + bootup(); + } + + /* + * Define the server side application of the test for the specified socket. + */ + protected abstract void runServerApplication(SSLSocket socket) throws Exception; + + /* + * Define the client side application of the test for the specified socket. + * This method is used if the returned value of + * isCustomizedClientConnection() is false. + * + * @param socket may be null is no client socket is generated. + * + * @see #isCustomizedClientConnection() + */ + protected abstract void runClientApplication(SSLSocket socket) throws Exception; + + /* + * Define the client side application of the test for the specified + * server port. This method is used if the returned value of + * isCustomizedClientConnection() is true. + * + * Note that the client need to connect to the server port by itself + * for the actual message exchange. + * + * @see #isCustomizedClientConnection() + */ + protected void runClientApplication(int serverPort) throws Exception { + // blank + } + + /* + * Create an instance of SSLContext for client use. + */ + protected SSLContext createClientSSLContext() throws Exception { + return createSSLContext(trustedCertStrs, + endEntityCertStrs, endEntityPrivateKeys, + endEntityPrivateKeyAlgs, + endEntityPrivateKeyNames, + getClientContextParameters()); + } + + /* + * Create an instance of SSLContext for server use. + */ + protected SSLContext createServerSSLContext() throws Exception { + return createSSLContext(trustedCertStrs, + endEntityCertStrs, endEntityPrivateKeys, + endEntityPrivateKeyAlgs, + endEntityPrivateKeyNames, + getServerContextParameters()); + } + + /* + * The parameters used to configure SSLContext. + */ + protected static final class ContextParameters { + final String contextProtocol; + final String tmAlgorithm; + final String kmAlgorithm; + + ContextParameters(String contextProtocol, + String tmAlgorithm, String kmAlgorithm) { + + this.contextProtocol = contextProtocol; + this.tmAlgorithm = tmAlgorithm; + this.kmAlgorithm = kmAlgorithm; + } + } + + /* + * Get the client side parameters of SSLContext. + */ + protected ContextParameters getClientContextParameters() { + return new ContextParameters("TLS", "PKIX", "NewSunX509"); + } + + /* + * Get the server side parameters of SSLContext. + */ + protected ContextParameters getServerContextParameters() { + return new ContextParameters("TLS", "PKIX", "NewSunX509"); + } + + /* + * Does the client side use customized connection other than + * explicit Socket.connect(), for example, URL.openConnection()? + */ + protected boolean isCustomizedClientConnection() { + return false; + } + + /* + * Configure the server side socket. + */ + protected void configureServerSocket(SSLServerSocket socket) { + + } + + /* + * ============================================= + * Define the client and server side operations. + * + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Is the server ready to serve? + */ + private final CountDownLatch serverCondition = new CountDownLatch(1); + + /* + * Is the client ready to handshake? + */ + private final CountDownLatch clientCondition = new CountDownLatch(1); + + /* + * What's the server port? Use any free port by default + */ + private volatile int serverPort = 0; + + /* + * Define the server side of the test. + */ + private void doServerSide() throws Exception { + // kick start the server side service + SSLContext context = createServerSSLContext(); + SSLServerSocketFactory sslssf = context.getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket)sslssf.createServerSocket(serverPort); + configureServerSocket(sslServerSocket); + serverPort = sslServerSocket.getLocalPort(); + + // Signal the client, the server is ready to accept connection. + serverCondition.countDown(); + + // Try to accept a connection in 30 seconds. + SSLSocket sslSocket; + try { + sslServerSocket.setSoTimeout(30000); + sslSocket = (SSLSocket)sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + // Ignore the test case if no connection within 30 seconds. + System.out.println( + "No incoming client connection in 30 seconds. " + + "Ignore in server side."); + return; + } finally { + sslServerSocket.close(); + } + + // handle the connection + try { + // Is it the expected client connection? + // + // Naughty test cases or third party routines may try to + // connection to this server port unintentionally. In + // order to mitigate the impact of unexpected client + // connections and avoid intermittent failure, it should + // be checked that the accepted connection is really linked + // to the expected client. + boolean clientIsReady = + clientCondition.await(30L, TimeUnit.SECONDS); + + if (clientIsReady) { + // Run the application in server side. + runServerApplication(sslSocket); + } else { // Otherwise, ignore + // We don't actually care about plain socket connections + // for TLS communication testing generally. Just ignore + // the test if the accepted connection is not linked to + // the expected client or the client connection timeout + // in 30 seconds. + System.out.println( + "The client is not the expected one or timeout. " + + "Ignore in server side."); + } + } finally { + sslSocket.close(); + } + } + + /* + * Define the client side of the test. + */ + private void doClientSide() throws Exception { + + // Wait for server to get started. + // + // The server side takes care of the issue if the server cannot + // get started in 90 seconds. The client side would just ignore + // the test case if the serer is not ready. + boolean serverIsReady = + serverCondition.await(90L, TimeUnit.SECONDS); + if (!serverIsReady) { + System.out.println( + "The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; + } + + if (isCustomizedClientConnection()) { + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + // Run the application in client side. + runClientApplication(serverPort); + + return; + } + + SSLContext context = createClientSSLContext(); + SSLSocketFactory sslsf = context.getSocketFactory(); + + try (SSLSocket sslSocket = (SSLSocket)sslsf.createSocket()) { + try { + sslSocket.connect( + new InetSocketAddress("localhost", serverPort), 15000); + } catch (IOException ioe) { + // The server side may be impacted by naughty test cases or + // third party routines, and cannot accept connections. + // + // Just ignore the test if the connection cannot be + // established. + System.out.println( + "Cannot make a connection in 15 seconds. " + + "Ignore in client side."); + return; + } + + // OK, here the client and server get connected. + + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + // There is still a chance in theory that the server thread may + // wait client-ready timeout and then quit. The chance should + // be really rare so we don't consider it until it becomes a + // real problem. + + // Run the application in client side. + runClientApplication(sslSocket); + } + } + + /* + * ============================================= + * Stuffs to customize the SSLContext instances. + */ + + /* + * ======================================= + * Certificates and keys used in the test. + */ + // Trusted certificates. + private final static String[] trustedCertStrs = { + // SHA256withECDSA, curve prime256v1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBvjCCAWOgAwIBAgIJAIvFG6GbTroCMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTBZ\n" + + "MBMGByqGSM49AgEGCCqGSM49AwEHA0IABBz1WeVb6gM2mh85z3QlvaB/l11b5h0v\n" + + "LIzmkC3DKlVukZT+ltH2Eq1oEkpXuf7QmbM0ibrUgtjsWH3mULfmcWmjUDBOMB0G\n" + + "A1UdDgQWBBRgz71z//oaMNKk7NNJcUbvGjWghjAfBgNVHSMEGDAWgBRgz71z//oa\n" + + "MNKk7NNJcUbvGjWghjAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMCA0kAMEYCIQCG\n" + + "6wluh1r2/T6L31mZXRKf9JxeSf9pIzoLj+8xQeUChQIhAJ09wAi1kV8yePLh2FD9\n" + + "2YEHlSQUAbwwqCDEVB5KxaqP\n" + + "-----END CERTIFICATE-----", + // -----BEGIN PRIVATE KEY----- + // MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg/HcHdoLJCdq3haVd + // XZTSKP00YzM3xX97l98vGL/RI1KhRANCAAQc9VnlW+oDNpofOc90Jb2gf5ddW+Yd + // LyyM5pAtwypVbpGU/pbR9hKtaBJKV7n+0JmzNIm61ILY7Fh95lC35nFp + // -----END PRIVATE KEY----- + + // SHA256withRSA, 2048 bits + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Subject Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIIDSTCCAjGgAwIBAgIJAI4ZF3iy8zG+MA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpMcY7aWieXDEM1/YJf\n" + + "JW27b4nRIFZyEYhEloyGsKTuQiiQjc8cqRZFNXe2vwziDB4IyTEl0Hjl5QF6ZaQE\n" + + "huPzzwvQm1pv64KrRXrmj3FisQK8B5OWLty9xp6xDqsaMRoyObLK+oIb20T5fSlE\n" + + "evmo1vYjnh8CX0Yzx5Gr5ye6YSEHQvYOWEws8ad17OlyToR2KMeC8w4qo6rs59pW\n" + + "g7Mxn9vo22ImDzrtAbTbXbCias3xlE0Bp0h5luyf+5U4UgksoL9B9r2oP4GrLNEV\n" + + "oJk57t8lwaR0upiv3CnS8LcJELpegZub5ggqLY8ZPYFQPjlK6IzLOm6rXPgZiZ3m\n" + + "RL0CAwEAAaNQME4wHQYDVR0OBBYEFA3dk8n+S701t+iZeJD721o92xVMMB8GA1Ud\n" + + "IwQYMBaAFA3dk8n+S701t+iZeJD721o92xVMMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + + "hvcNAQELBQADggEBAJTRC3rKUUhVH07/1+stUungSYgpM08dY4utJq0BDk36BbmO\n" + + "0AnLDMbkwFdHEoqF6hQIfpm7SQTmXk0Fss6Eejm8ynYr6+EXiRAsaXOGOBCzF918\n" + + "/RuKOzqABfgSU4UBKECLM5bMfQTL60qx+HdbdVIpnikHZOFfmjCDVxoHsGyXc1LW\n" + + "Jhkht8IGOgc4PMGvyzTtRFjz01kvrVQZ75aN2E0GQv6dCxaEY0i3ypSzjUWAKqDh\n" + + "3e2OLwUSvumcdaxyCdZAOUsN6pDBQ+8VRG7KxnlRlY1SMEk46QgQYLbPDe/+W/yH\n" + + "ca4PejicPeh+9xRAwoTpiE2gulfT7Lm+fVM7Ruc=\n" + + "-----END CERTIFICATE-----", + // -----BEGIN PRIVATE KEY----- + // MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6THGO2lonlwxD + // Nf2CXyVtu2+J0SBWchGIRJaMhrCk7kIokI3PHKkWRTV3tr8M4gweCMkxJdB45eUB + // emWkBIbj888L0Jtab+uCq0V65o9xYrECvAeTli7cvcaesQ6rGjEaMjmyyvqCG9tE + // +X0pRHr5qNb2I54fAl9GM8eRq+cnumEhB0L2DlhMLPGndezpck6EdijHgvMOKqOq + // 7OfaVoOzMZ/b6NtiJg867QG0212womrN8ZRNAadIeZbsn/uVOFIJLKC/Qfa9qD+B + // qyzRFaCZOe7fJcGkdLqYr9wp0vC3CRC6XoGbm+YIKi2PGT2BUD45SuiMyzpuq1z4 + // GYmd5kS9AgMBAAECggEAFHSoU2MuWwJ+2jJnb5U66t2V1bAcuOE1g5zkWvG/G5z9 + // rq6Qo5kmB8f5ovdx6tw3MGUOklLwnRXBG3RxDJ1iokz3AvkY1clMNsDPlDsUrQKF + // JSO4QUBQTPSZhnsyfR8XHSU+qJ8Y+ohMfzpVv95BEoCzebtXdVgxVegBlcEmVHo2 + // kMmkRN+bYNsr8eb2r+b0EpyumS39ZgKYh09+cFb78y3T6IFMGcVJTP6nlGBFkmA/ + // 25pYeCF2tSki08qtMJZQAvKfw0Kviibk7ZxRbJqmc7B1yfnOEHP6ftjuvKl2+RP/ + // +5P5f8CfIP6gtA0LwSzAqQX/hfIKrGV5j0pCqrD0kQKBgQDeNR6Xi4sXVq79lihO + // a1bSeV7r8yoQrS8x951uO+ox+UIZ1MsAULadl7zB/P0er92p198I9M/0Jth3KBuS + // zj45mucvpiiGvmQlMKMEfNq4nN7WHOu55kufPswQB2mR4J3xmwI+4fM/nl1zc82h + // De8JSazRldJXNhfx0RGFPmgzbwKBgQDWoVXrXLbCAn41oVnWB8vwY9wjt92ztDqJ + // HMFA/SUohjePep9UDq6ooHyAf/Lz6oE5NgeVpPfTDkgvrCFVKnaWdwALbYoKXT2W + // 9FlyJox6eQzrtHAacj3HJooXWuXlphKSizntfxj3LtMR9BmrmRJOfK+SxNOVJzW2 + // +MowT20EkwKBgHmpB8jdZBgxI7o//m2BI5Y1UZ1KE5vx1kc7VXzHXSBjYqeV9FeF + // 2ZZLP9POWh/1Fh4pzTmwIDODGT2UPhSQy0zq3O0fwkyT7WzXRknsuiwd53u/dejg + // iEL2NPAJvulZ2+AuiHo5Z99LK8tMeidV46xoJDDUIMgTG+UQHNGhK5gNAoGAZn/S + // Cn7SgMC0CWSvBHnguULXZO9wH1wZAFYNLL44OqwuaIUFBh2k578M9kkke7woTmwx + // HxQTjmWpr6qimIuY6q6WBN8hJ2Xz/d1fwhYKzIp20zHuv5KDUlJjbFfqpsuy3u1C + // kts5zwI7pr1ObRbDGVyOdKcu7HI3QtR5qqyjwaUCgYABo7Wq6oHva/9V34+G3Goh + // 63bYGUnRw2l5BD11yhQv8XzGGZFqZVincD8gltNThB0Dc/BI+qu3ky4YdgdZJZ7K + // z51GQGtaHEbrHS5caV79yQ8QGY5mUVH3E+VXSxuIqb6pZq2DH4sTAEFHyncddmOH + // zoXBInYwRG9KE/Bw5elhUw== + // -----END PRIVATE KEY----- + + // SHA256withDSA, 2048 bits + // Validity + // Not Before: May 22 07:18:18 2018 GMT + // Not After : May 17 07:18:18 2038 GMT + // Subject Key Identifier: + // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 + "-----BEGIN CERTIFICATE-----\n" + + "MIIErjCCBFSgAwIBAgIJAOktYLNCbr02MAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2UwHhcNMTgwNTIyMDcxODE4WhcNMzgwNTE3MDcxODE4WjA7MQswCQYDVQQGEwJV\n" + + "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Uw\n" + + "ggNHMIICOQYHKoZIzjgEATCCAiwCggEBAO5GyPhSm0ze3LSu+gicdULLj05iOfTL\n" + + "UvZQ29sYz41zmqrLBQbdKiHqgJu2Re9sgTb5suLNjF047TOLPnU3jhPtWm2X8Xzi\n" + + "VGIcHym/Q/MeZxStt/88seqroI3WOKzIML2GcrishT+lcGrtH36Tf1+ue2Snn3PS\n" + + "WyxygNqPjllP5uUjYmFLvAf4QLMldkd/D2VxcwsHjB8y5iUZsXezc/LEhRZS/02m\n" + + "ivqlRw3AMkq/OVe/ZtxFWsP0nsfxEGdZuaUFpppGfixxFvymrB3+J51cTt+pZBDq\n" + + "D2y0DYfc+88iCs4jwHTfcDIpLb538HBjBj2rEgtQESQmB0ooD/+wsPsCIQC1bYch\n" + + "gElNtDYL3FgpLgNSUYp7gIWv9ehaC7LO2z7biQKCAQBitvFOnDkUja8NAF7lDpOV\n" + + "b5ipQ8SicBLW3kQamxhyuyxgZyy/PojZ/oPorkqW/T/A0rhnG6MssEpAtdiwVB+c\n" + + "rBYGo3bcwmExJhdOJ6dYuKFppPWhCwKMHs9npK+lqBMl8l5j58xlcFeC7ZfGf8GY\n" + + "GkhFW0c44vEQhMMbac6ZTTP4mw+1t7xJfmDMlLEyIpTXaAAk8uoVLWzQWnR40sHi\n" + + "ybvS0u3JxQkb7/y8tOOZu8qlz/YOS7lQ6UxUGX27Ce1E0+agfPphetoRAlS1cezq\n" + + "Wa7r64Ga0nkj1kwkcRqjgTiJx0NwnUXr78VAXFhVF95+O3lfqhvdtEGtkhDGPg7N\n" + + "A4IBBgACggEBAMmSHQK0w2i+iqUjOPzn0yNEZrzepLlLeQ1tqtn0xnlv5vBAeefD\n" + + "Pm9dd3tZOjufVWP7hhEz8xPobb1CS4e3vuQiv5UBfhdPL3f3l9T7JMAKPH6C9Vve\n" + + "OQXE5eGqbjsySbcmseHoYUt1WCSnSda1opX8zchX04e7DhGfE2/L9flpYEoSt8lI\n" + + "vMNjgOwvKdW3yvPt1/eBBHYNFG5gWPv/Q5KoyCtHS03uqGm4rNc/wZTIEEfd66C+\n" + + "QRaUltjOaHmtwOdDHaNqwhYZSVOip+Mo+TfyzHFREcdHLapo7ZXqbdYkRGxRR3d+\n" + + "3DfHaraJO0OKoYlPkr3JMvM/MSGR9AnZOcejUDBOMB0GA1UdDgQWBBR2Zp73O91F\n" + + "5TvZcjw/8FQ5hjEmUzAfBgNVHSMEGDAWgBR2Zp73O91F5TvZcjw/8FQ5hjEmUzAM\n" + + "BgNVHRMEBTADAQH/MAsGCWCGSAFlAwQDAgNHADBEAiBzriYE41M2y9Hy5ppkL0Qn\n" + + "dIlNc8JhXT/PHW7GDtViagIgMko8Qoj9gDGPK3+O9E8DC3wGiiF9CObM4LN387ok\n" + + "J+g=\n" + + "-----END CERTIFICATE-----" + // -----BEGIN PRIVATE KEY----- + // MIICZQIBADCCAjkGByqGSM44BAEwggIsAoIBAQDuRsj4UptM3ty0rvoInHVCy49O + // Yjn0y1L2UNvbGM+Nc5qqywUG3Soh6oCbtkXvbIE2+bLizYxdOO0ziz51N44T7Vpt + // l/F84lRiHB8pv0PzHmcUrbf/PLHqq6CN1jisyDC9hnK4rIU/pXBq7R9+k39frntk + // p59z0lsscoDaj45ZT+blI2JhS7wH+ECzJXZHfw9lcXMLB4wfMuYlGbF3s3PyxIUW + // Uv9Npor6pUcNwDJKvzlXv2bcRVrD9J7H8RBnWbmlBaaaRn4scRb8pqwd/iedXE7f + // qWQQ6g9stA2H3PvPIgrOI8B033AyKS2+d/BwYwY9qxILUBEkJgdKKA//sLD7AiEA + // tW2HIYBJTbQ2C9xYKS4DUlGKe4CFr/XoWguyzts+24kCggEAYrbxTpw5FI2vDQBe + // 5Q6TlW+YqUPEonAS1t5EGpsYcrssYGcsvz6I2f6D6K5Klv0/wNK4ZxujLLBKQLXY + // sFQfnKwWBqN23MJhMSYXTienWLihaaT1oQsCjB7PZ6SvpagTJfJeY+fMZXBXgu2X + // xn/BmBpIRVtHOOLxEITDG2nOmU0z+JsPtbe8SX5gzJSxMiKU12gAJPLqFS1s0Fp0 + // eNLB4sm70tLtycUJG+/8vLTjmbvKpc/2Dku5UOlMVBl9uwntRNPmoHz6YXraEQJU + // tXHs6lmu6+uBmtJ5I9ZMJHEao4E4icdDcJ1F6+/FQFxYVRfefjt5X6ob3bRBrZIQ + // xj4OzQQjAiEAsceWOM8do4etxp2zgnoNXV8PUUyqWhz1+0srcKV7FR4= + // -----END PRIVATE KEY----- + }; + + // End entity certificate. + private final static String[] endEntityCertStrs = { + // SHA256withECDSA, curve prime256v1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 60:CF:BD:73:FF:FA:1A:30:D2:A4:EC:D3:49:71:46:EF:1A:35:A0:86 + "-----BEGIN CERTIFICATE-----\n" + + "MIIBqjCCAVCgAwIBAgIJAPLY8qZjgNRAMAoGCCqGSM49BAMCMDsxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYTAlVT\n" + + "MQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZjZTEY\n" + + "MBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n" + + "QgAEb+9n05qfXnfHUb0xtQJNS4JeSi6IjOfW5NqchvKnfJey9VkJzR7QHLuOESdf\n" + + "xlR7q8YIWgih3iWLGfB+wxHiOqMjMCEwHwYDVR0jBBgwFoAUYM+9c//6GjDSpOzT\n" + + "SXFG7xo1oIYwCgYIKoZIzj0EAwIDSAAwRQIgWpRegWXMheiD3qFdd8kMdrkLxRbq\n" + + "1zj8nQMEwFTUjjQCIQDRIrAjZX+YXHN9b0SoWWLPUq0HmiFIi8RwMnO//wJIGQ==\n" + + "-----END CERTIFICATE-----", + + // SHA256withRSA, 2048 bits + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 17 07:18:16 2038 GMT + // Authority Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIIDNjCCAh6gAwIBAgIJAO2+yPcFryUTMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0zODA1MTcwNzE4MTZaMFUxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOC\n" + + "AQ8AMIIBCgKCAQEAszfBobWfZIp8AgC6PiWDDavP65mSvgCXUGxACbxVNAfkLhNR\n" + + "QOsHriRB3X1Q3nvO9PetC6wKlvE9jlnDDj7D+1j1r1CHO7ms1fq8rfcQYdkanDtu\n" + + "4AlHo8v+SSWX16MIXFRYDj2VVHmyPtgbltcg4zGAuwT746FdLI94uXjJjq1IOr/v\n" + + "0VIlwE5ORWH5Xc+5Tj+oFWK0E4a4GHDgtKKhn2m72hN56/GkPKGkguP5NRS1qYYV\n" + + "/EFkdyQMOV8J1M7HaicSft4OL6eKjTrgo93+kHk+tv0Dc6cpVBnalX3TorG8QI6B\n" + + "cHj1XQd78oAlAC+/jF4pc0mwi0un49kdK9gRfQIDAQABoyMwITAfBgNVHSMEGDAW\n" + + "gBQN3ZPJ/ku9NbfomXiQ+9taPdsVTDANBgkqhkiG9w0BAQsFAAOCAQEApXS0nKwm\n" + + "Kp8gpmO2yG1rpd1+2wBABiMU4JZaTqmma24DQ3RzyS+V2TeRb29dl5oTUEm98uc0\n" + + "GPZvhK8z5RFr4YE17dc04nI/VaNDCw4y1NALXGs+AHkjoPjLyGbWpi1S+gfq2sNB\n" + + "Ekkjp6COb/cb9yiFXOGVls7UOIjnVZVd0r7KaPFjZhYh82/f4PA/A1SnIKd1+nfH\n" + + "2yk7mSJNC7Z3qIVDL8MM/jBVwiC3uNe5GPB2uwhd7k5LGAVN3j4HQQGB0Sz+VC1h\n" + + "92oi6xDa+YBva2fvHuCd8P50DDjxmp9CemC7rnZ5j8egj88w14X44Xjb/Fd/ApG9\n" + + "e57NnbT7KM+Grw==\n" + + "-----END CERTIFICATE-----", + + // SHA256withRSA, curv prime256v1 + // Validity + // Not Before: May 22 07:18:16 2018 GMT + // Not After : May 21 07:18:16 2028 GMT + // Authority Key Identifier: + // 0D:DD:93:C9:FE:4B:BD:35:B7:E8:99:78:90:FB:DB:5A:3D:DB:15:4C + "-----BEGIN CERTIFICATE-----\n" + + "MIICazCCAVOgAwIBAgIJAO2+yPcFryUUMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNV\n" + + "BAYTAlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2Vy\n" + + "aXZjZTAeFw0xODA1MjIwNzE4MTZaFw0yODA1MjEwNzE4MTZaMFUxCzAJBgNVBAYT\n" + + "AlVTMQ0wCwYDVQQKDARKYXZhMR0wGwYDVQQLDBRTdW5KU1NFIFRlc3QgU2VyaXZj\n" + + "ZTEYMBYGA1UEAwwPUmVncmVzc2lvbiBUZXN0MFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" + + "AQcDQgAE59MERNTlVZ1eeps8Z3Oue5ZkgQdPtD+WIE6tj3PbIKpxGPDxvfNP959A\n" + + "yQjEK/ehWQVrCMmNoEkIzY+IIBgB06MjMCEwHwYDVR0jBBgwFoAUDd2Tyf5LvTW3\n" + + "6Jl4kPvbWj3bFUwwDQYJKoZIhvcNAQELBQADggEBAFOTVEqs70ykhZiIdrEsF1Ra\n" + + "I3B2rLvwXZk52uSltk2/bzVvewA577ZCoxQ1pL7ynkisPfBN1uVYtHjM1VA3RC+4\n" + + "+TAK78dnI7otYjWoHp5rvs4l6c/IbOspS290IlNuDUxMErEm5wxIwj+Aukx/1y68\n" + + "hOyCvHBLMY2c1LskH1MMBbDuS1aI+lnGpToi+MoYObxGcV458vxuT8+wwV8Fkpvd\n" + + "ll8IIFmeNPRv+1E+lXbES6CSNCVaZ/lFhPgdgYKleN7sfspiz50DG4dqafuEAaX5\n" + + "xaK1NWXJxTRz0ROH/IUziyuDW6jphrlgit4+3NCzp6vP9hAJQ8Vhcj0n15BKHIQ=\n" + + "-----END CERTIFICATE-----", + + // SHA256withDSA, 2048 bits + // Validity + // Not Before: May 22 07:18:20 2018 GMT + // Not After : May 17 07:18:20 2038 GMT + // Authority Key Identifier: + // 76:66:9E:F7:3B:DD:45:E5:3B:D9:72:3C:3F:F0:54:39:86:31:26:53 + "-----BEGIN CERTIFICATE-----\n" + + "MIIEnDCCBEGgAwIBAgIJAP/jh1qVhNVjMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2UwHhcNMTgwNTIyMDcxODIwWhcNMzgwNTE3MDcxODIwWjBVMQswCQYDVQQGEwJV\n" + + "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" + + "GDAWBgNVBAMMD1JlZ3Jlc3Npb24gVGVzdDCCA0cwggI6BgcqhkjOOAQBMIICLQKC\n" + + "AQEAmlavgoJrMcjqWRVcDE2dmWAPREgnzQvneEDef68cprDzjSwvOs5QeFyx75ib\n" + + "ado1e6jO/rW1prCGWHDD1oA/Tn4Pk3vu0nUxzvl1qATc+aJbpUU5Op0bvp6LbCsQ\n" + + "QslV9FeRh7Eb7bP6gpc/kHCBzEgC1VCK7prccXWy+t6SMOHbND3h+UbckfSaUuaV\n" + + "sVJNTD1D6GElfRj4Nmz1BGPfSYvKorwNZEU3gXwFgtDoAcGx7tcyClLpDHfqRfw/\n" + + "7yiqLyeiP7D4hl5lMNouJWDlAdMFp0FMgS3s9VDFinIcr6VtBWMTG7+4+czHAB+3\n" + + "fvrwlqNzhBn3uFHrekN/w8fNxwIhAJo7Sae1za7IMW0Q6hE5B4b+s2B/FaKPoA4E\n" + + "jtZu13B9AoIBAQCOZqLMKfvqZWUgT0PQ3QjR7dAFdd06I9Y3+TOQzZk1+j+vw/6E\n" + + "X4vFItX4gihb/u5Q9CdmpwhVGi7bvo+7+/IKeTgoQ6f5+PSug7SrWWUQ5sPwaZui\n" + + "zXZJ5nTeZDucFc2yFx0wgnjbPwiUxZklOT7xGiOMtzOTa2koCz5KuIBL+/wPKKxm\n" + + "ypo9VoY9xfbdU6LMXZv/lpD5XTM9rYHr/vUTNkukvV6Hpm0YMEWhVZKUJiqCqTqG\n" + + "XHaleOxSw6uQWB/+TznifcC7gB48UOQjCqOKf5VuwQneJLhlhU/jhRV3xtr+hLZa\n" + + "hW1wYhVi8cjLDrZFKlgEQqhB4crnJU0mJY+tA4IBBQACggEAID0ezl00/X8mv7eb\n" + + "bzovum1+DEEP7FM57k6HZEG2N3ve4CW+0m9Cd+cWPz8wkZ+M0j/Eqa6F0IdbkXEc\n" + + "Q7CuzvUyJ57xQ3L/WCgXsiS+Bh8O4Mz7GwW22CGmHqafbVv+hKBfr8MkskO6GJUt\n" + + "SUF/CVLzB4gMIvZMH26tBP2xK+i7FeEK9kT+nGdzQSZBAhFYpEVCBplHZO24/OYq\n" + + "1DNoU327nUuXIhmsfA8N0PjiWbIZIjTPwBGr9H0LpATI7DIDNcvRRvtROP+pBU9y\n" + + "fuykPkptg9C0rCM9t06bukpOSaEz/2VIQdLE8fHYFA6pHZ6CIc2+5cfvMgTPhcjz\n" + + "W2jCt6MjMCEwHwYDVR0jBBgwFoAUdmae9zvdReU72XI8P/BUOYYxJlMwCwYJYIZI\n" + + "AWUDBAMCA0gAMEUCIQCeI5fN08b9BpOaHdc3zQNGjp24FOL/RxlBLeBAorswJgIg\n" + + "JEZ8DhYxQy1O7mmZ2UIT7op6epWMB4dENjs0qWPmcKo=\n" + + "-----END CERTIFICATE-----" + }; + + // Private key in the format of PKCS#8. + private final static String[] endEntityPrivateKeys = { + // + // EC private key related to cert endEntityCertStrs[0]. + // + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgn5K03bpTLjEtFQRa\n" + + "JUtx22gtmGEvvSUSQdimhGthdtihRANCAARv72fTmp9ed8dRvTG1Ak1Lgl5KLoiM\n" + + "59bk2pyG8qd8l7L1WQnNHtAcu44RJ1/GVHurxghaCKHeJYsZ8H7DEeI6", + + // + // RSA private key related to cert endEntityCertStrs[1]. + // + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzN8GhtZ9kinwC\n" + + "ALo+JYMNq8/rmZK+AJdQbEAJvFU0B+QuE1FA6weuJEHdfVDee870960LrAqW8T2O\n" + + "WcMOPsP7WPWvUIc7uazV+ryt9xBh2RqcO27gCUejy/5JJZfXowhcVFgOPZVUebI+\n" + + "2BuW1yDjMYC7BPvjoV0sj3i5eMmOrUg6v+/RUiXATk5FYfldz7lOP6gVYrQThrgY\n" + + "cOC0oqGfabvaE3nr8aQ8oaSC4/k1FLWphhX8QWR3JAw5XwnUzsdqJxJ+3g4vp4qN\n" + + "OuCj3f6QeT62/QNzpylUGdqVfdOisbxAjoFwePVdB3vygCUAL7+MXilzSbCLS6fj\n" + + "2R0r2BF9AgMBAAECggEASIkPkMCuw4WdTT44IwERus3IOIYOs2IP3BgEDyyvm4B6\n" + + "JP/iihDWKfA4zEl1Gqcni1RXMHswSglXra682J4kui02Ov+vzEeJIY37Ibn2YnP5\n" + + "ZjRT2s9GtI/S2o4hl8A/mQb2IMViFC+xKehTukhV4j5d6NPKk0XzLR7gcMjnYxwn\n" + + "l21fS6D2oM1xRG/di7sL+uLF8EXLRzfiWDNi12uQv4nwtxPKvuKhH6yzHt7YqMH0\n" + + "46pmDKDaxV4w1JdycjCb6NrCJOYZygoQobuZqOQ30UZoZsPJrtovkncFr1e+lNcO\n" + + "+aWDfOLCtTH046dEQh5oCShyXMybNlry/QHsOtHOwQKBgQDh2iIjs+FPpQy7Z3EX\n" + + "DGEvHYqPjrYO9an2KSRr1m9gzRlWYxKY46WmPKwjMerYtra0GP+TBHrgxsfO8tD2\n" + + "wUAII6sd1qup0a/Sutgf2JxVilLykd0+Ge4/Cs51tCdJ8EqDV2B6WhTewOY2EGvg\n" + + "JiKYkeNwgRX/9M9CFSAMAk0hUQKBgQDLJAartL3DoGUPjYtpJnfgGM23yAGl6G5r\n" + + "NSXDn80BiYIC1p0bG3N0xm3yAjqOtJAUj9jZbvDNbCe3GJfLARMr23legX4tRrgZ\n" + + "nEdKnAFKAKL01oM+A5/lHdkwaZI9yyv+hgSVdYzUjB8rDmzeVQzo1BT7vXypt2yV\n" + + "6O1OnUpCbQKBgA/0rzDChopv6KRcvHqaX0tK1P0rYeVQqb9ATNhpf9jg5Idb3HZ8\n" + + "rrk91BNwdVz2G5ZBpdynFl9G69rNAMJOCM4KZw5mmh4XOEq09Ivba8AHU7DbaTv3\n" + + "7QL7KnbaUWRB26HHzIMYVh0el6T+KADf8NXCiMTr+bfpfbL3dxoiF3zhAoGAbCJD\n" + + "Qse1dBs/cKYCHfkSOsI5T6kx52Tw0jS6Y4X/FOBjyqr/elyEexbdk8PH9Ar931Qr\n" + + "NKMvn8oA4iA/PRrXX7M2yi3YQrWwbkGYWYjtzrzEAdzmg+5eARKAeJrZ8/bg9l3U\n" + + "ttKaItJsDPlizn8rngy3FsJpR9aSAMK6/+wOiYkCgYEA1tZkI1rD1W9NYZtbI9BE\n" + + "qlJVFi2PBOJMKNuWdouPX3HLQ72GJSQff2BFzLTELjweVVJ0SvY4IipzpQOHQOBy\n" + + "5qh/p6izXJZh3IHtvwVBjHoEVplg1b2+I5e3jDCfqnwcQw82dW5SxOJMg1h/BD0I\n" + + "qAL3go42DYeYhu/WnECMeis=", + + // + // EC private key related to cert endEntityCertStrs[2]. + // + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGVc7hICpmp91jbYe\n" + + "nrr8nYHD37RZP3VENY+szuA7WjuhRANCAATn0wRE1OVVnV56mzxnc657lmSBB0+0\n" + + "P5YgTq2Pc9sgqnEY8PG980/3n0DJCMQr96FZBWsIyY2gSQjNj4ggGAHT", + + // + // DSA private key related to cert endEntityCertStrs[3]. + // + "MIICZQIBADCCAjoGByqGSM44BAEwggItAoIBAQCaVq+CgmsxyOpZFVwMTZ2ZYA9E\n" + + "SCfNC+d4QN5/rxymsPONLC86zlB4XLHvmJtp2jV7qM7+tbWmsIZYcMPWgD9Ofg+T\n" + + "e+7SdTHO+XWoBNz5olulRTk6nRu+notsKxBCyVX0V5GHsRvts/qClz+QcIHMSALV\n" + + "UIrumtxxdbL63pIw4ds0PeH5RtyR9JpS5pWxUk1MPUPoYSV9GPg2bPUEY99Ji8qi\n" + + "vA1kRTeBfAWC0OgBwbHu1zIKUukMd+pF/D/vKKovJ6I/sPiGXmUw2i4lYOUB0wWn\n" + + "QUyBLez1UMWKchyvpW0FYxMbv7j5zMcAH7d++vCWo3OEGfe4Uet6Q3/Dx83HAiEA\n" + + "mjtJp7XNrsgxbRDqETkHhv6zYH8Voo+gDgSO1m7XcH0CggEBAI5moswp++plZSBP\n" + + "Q9DdCNHt0AV13Toj1jf5M5DNmTX6P6/D/oRfi8Ui1fiCKFv+7lD0J2anCFUaLtu+\n" + + "j7v78gp5OChDp/n49K6DtKtZZRDmw/Bpm6LNdknmdN5kO5wVzbIXHTCCeNs/CJTF\n" + + "mSU5PvEaI4y3M5NraSgLPkq4gEv7/A8orGbKmj1Whj3F9t1Tosxdm/+WkPldMz2t\n" + + "gev+9RM2S6S9XoembRgwRaFVkpQmKoKpOoZcdqV47FLDq5BYH/5POeJ9wLuAHjxQ\n" + + "5CMKo4p/lW7BCd4kuGWFT+OFFXfG2v6EtlqFbXBiFWLxyMsOtkUqWARCqEHhyucl\n" + + "TSYlj60EIgIgLfA75+8KcKxdN8mr6gzGjQe7jPFGG42Ejhd7Q2F4wuw=" + }; + + // Private key algorithm of endEntityPrivateKeys. + private final static String[] endEntityPrivateKeyAlgs = { + "EC", + "RSA", + "EC", + "DSA", + }; + + // Private key names of endEntityPrivateKeys. + private final static String[] endEntityPrivateKeyNames = { + "ecdsa", + "rsa", + "ec-rsa", + "dsa", + }; + + /* + * Create an instance of SSLContext with the specified trust/key materials. + */ + private SSLContext createSSLContext( + String[] trustedMaterials, + String[] keyMaterialCerts, + String[] keyMaterialKeys, + String[] keyMaterialKeyAlgs, + String[] keyMaterialKeyNames, + ContextParameters params) throws Exception { + + KeyStore ts = null; // trust store + KeyStore ks = null; // key store + char passphrase[] = "passphrase".toCharArray(); + + // Generate certificate from cert string. + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + // Import the trused certs. + ByteArrayInputStream is; + if (trustedMaterials != null && trustedMaterials.length != 0) { + ts = KeyStore.getInstance("JKS"); + ts.load(null, null); + + Certificate[] trustedCert = + new Certificate[trustedMaterials.length]; + for (int i = 0; i < trustedMaterials.length; i++) { + String trustedCertStr = trustedMaterials[i]; + + is = new ByteArrayInputStream(trustedCertStr.getBytes()); + try { + trustedCert[i] = cf.generateCertificate(is); + } finally { + is.close(); + } + + ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]); + } + } + + // Import the key materials. + // + // Note that certification pathes bigger than one are not supported yet. + boolean hasKeyMaterials = + (keyMaterialCerts != null) && (keyMaterialCerts.length != 0) && + (keyMaterialKeys != null) && (keyMaterialKeys.length != 0) && + (keyMaterialKeyAlgs != null) && (keyMaterialKeyAlgs.length != 0) && + (keyMaterialCerts.length == keyMaterialKeys.length) && + (keyMaterialCerts.length == keyMaterialKeyAlgs.length); + if (hasKeyMaterials) { + ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + for (int i = 0; i < keyMaterialCerts.length; i++) { + String keyCertStr = keyMaterialCerts[i]; + + // generate the private key. + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keyMaterialKeys[i])); + KeyFactory kf = + KeyFactory.getInstance(keyMaterialKeyAlgs[i]); + PrivateKey priKey = kf.generatePrivate(priKeySpec); + + // generate certificate chain + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = null; + try { + keyCert = cf.generateCertificate(is); + } finally { + is.close(); + } + + Certificate[] chain = new Certificate[] { keyCert }; + + // import the key entry. + ks.setKeyEntry("cert-" + keyMaterialKeyNames[i], + priKey, passphrase, chain); + } + } + + // Create an SSLContext object. + TrustManagerFactory tmf = + TrustManagerFactory.getInstance(params.tmAlgorithm); + tmf.init(ts); + + SSLContext context = SSLContext.getInstance(params.contextProtocol); + if (hasKeyMaterials && ks != null) { + KeyManagerFactory kmf = + KeyManagerFactory.getInstance(params.kmAlgorithm); + kmf.init(ks, passphrase); + + context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + } else { + context.init(null, tmf.getTrustManagers(), null); + } + + return context; + } + + /* + * ================================================= + * Stuffs to boot up the client-server mode testing. + */ + private Thread clientThread = null; + private Thread serverThread = null; + private volatile Exception serverException = null; + private volatile Exception clientException = null; + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + private static final boolean separateServerThread = false; + + /* + * Boot up the testing, used to drive remainder of the test. + */ + private void bootup() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + private void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + logException("Server died", e); + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + logException("Server failed", e); + serverException = e; + } + } + } + + private void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + logException("Client died", e); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + logException("Client failed", e); + clientException = e; + } + } + } + + private synchronized void logException(String prefix, Throwable cause) { + System.out.println(prefix + ": " + cause); + cause.printStackTrace(System.out); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/SecurityUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/SecurityUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -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 jdk.test.lib.security; + +import java.io.File; +import java.security.KeyStore; + +/** + * Common library for various security test helper functions. + */ +public final class SecurityUtils { + + private static String getCacerts() { + String sep = File.separator; + return System.getProperty("java.home") + sep + + "lib" + sep + "security" + sep + "cacerts"; + } + + /** + * Returns the cacerts keystore with the configured CA certificates. + */ + public static KeyStore getCacertsKeyStore() throws Exception { + File file = new File(getCacerts()); + if (!file.exists()) { + return null; + } + return KeyStore.getInstance(file, (char[])null); + } + + private SecurityUtils() {} +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/TestCertificate.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/TestCertificate.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,175 @@ +/* + * 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 jdk.test.lib.security; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertPath; +import java.security.cert.CertPathValidator; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.PKIXParameters; +import java.security.cert.TrustAnchor; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +// Certificates taken from old ValWithAnchorByName testcase *** +public enum TestCertificate { + // Subject: CN=SSLCertificate, O=SomeCompany + // Issuer: CN=Intermediate CA Cert, O=SomeCompany + // Validity: Tue Aug 30 14:37:19 PDT 2016 to Wed Aug 30 14:37:19 PDT 2017 + ONE("1000", + "CN=SSLCertificate, O=SomeCompany", + "CN=Intermediate CA Cert, O=SomeCompany", + -1063259762, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDnTCCAoWgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwNTEUMBIGA1UEChMLU29t\n" + + "ZUNvbXBhbnkxHTAbBgNVBAMTFEludGVybWVkaWF0ZSBDQSBDZXJ0MB4XDTE2MDgz\n" + + "MDIxMzcxOVoXDTE3MDgzMDIxMzcxOVowLzEUMBIGA1UEChMLU29tZUNvbXBhbnkx\n" + + "FzAVBgNVBAMTDlNTTENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\n" + + "MIIBCgKCAQEAjgv8KKE4CO0rbCjRLA1hXjRiSq30jeusCJ8frbRG+QOBgQ3j6jgc\n" + + "vk5wG1aTu7R4AFn0/HRDMzP9ZbRlZVIbJUTd8YiaNyZeyWapPnxHWrPCd5e1xopk\n" + + "ElieDdEH5FiLGtIrWy56CGA1hfQb1vUVYegyeY+TTtMFVHt0PrmMk4ZRgj/GtVNp\n" + + "BQQYIzaYAcrcWMeCn30ZrhaGAL1hsdgmEVV1wsTD4JeNMSwLwMYem7fg8ondGZIR\n" + + "kZuGtuSdOHu4Xz+mgDNXTeX/Bp/dQFucxCG+FOOM9Hoz72RY2W8YqgL38RlnwYWp\n" + + "nUNxhXWFH6vyINRQVEu3IgahR6HXjxM7LwIDAQABo4G8MIG5MBQGA1UdEQQNMAuC\n" + + "CWxvY2FsaG9zdDAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9s\n" + + "b2NhbGhvc3Q6NDIzMzMwHwYDVR0jBBgwFoAUYT525lwHCI4CmuWs8a7poaeKRJ4w\n" + + "HQYDVR0OBBYEFCaQnOX4L1ovqyfeKuoay+kI+lXgMA4GA1UdDwEB/wQEAwIFoDAd\n" + + "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB\n" + + "AD8dqQIqFasJcL8lm4mPTsBl0JgNiN8tQcXM7VCvcH+yDvEyh9vudDjuhpSORqPq\n" + + "f1o/EvJ+gfs269mBnYQujYRvmSd6EAcBntv5zn6amOh03o6PqTY9KaUC/mL9hB84\n" + + "Y5/LYioP16sME7egKnlrGUgKh0ZvGzm7c3SYx3Z5YoeFBOkZajc7Jm+cBw/uBQkF\n" + + "a9mLEczIvOgkq1wto8vr2ptH1gEuvFRcorN3muvq34bk40G08+AHlP3fCLFpI3FA\n" + + "IStJLJZRcO+Ib4sOcKuaBGnuMo/QVOCEMDUs6RgiWtSd93OZKFIUOASVp6YIkcSs\n" + + "5/rmc06sICqBjLfPEB68Jjw=\n" + + "-----END CERTIFICATE-----"), + // Subject: CN=Intermediate CA Cert, O=SomeCompany + // Issuer: CN=Root CA Cert, O=SomeCompany + // Validity: Sun Aug 07 14:37:19 PDT 2016 to Tue Aug 07 14:37:19 PDT 2018 + TWO("64", + "CN=Intermediate CA Cert, O=SomeCompany", + "CN=Root CA Cert, O=SomeCompany", + -927189373, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDdjCCAl6gAwIBAgIBZDANBgkqhkiG9w0BAQsFADAtMRQwEgYDVQQKEwtTb21l\n" + + "Q29tcGFueTEVMBMGA1UEAxMMUm9vdCBDQSBDZXJ0MB4XDTE2MDgwNzIxMzcxOVoX\n" + + "DTE4MDgwNzIxMzcxOVowNTEUMBIGA1UEChMLU29tZUNvbXBhbnkxHTAbBgNVBAMT\n" + + "FEludGVybWVkaWF0ZSBDQSBDZXJ0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n" + + "CgKCAQEAnJR5CnE7GKlQjigExSJ6hHu302mc0PcA6TDgsIitPYD/r8RBbBuE51OQ\n" + + "7IP7AXmfPUV3/+pO/uxx6mgY5O6XeUl7KadhVPtPcL0BVVevCSOdTMVa3iV4zRpa\n" + + "C6Uy2ouUFnafKnDtlbieggyETUoNgVNJYA9L0XNhtSnENoLHC4Pq0v8OsNtsOWFR\n" + + "NiMTOA49NNDBw85WgPyFAxjqO4z0J0zxdWq3W4rSMB8xrkulv2Rvj3GcfYJK/ab8\n" + + "V1IJ6PMWCpujASY3BzvYPnN7BKuBjbWJPgZdPYfX1cxeG80u0tOuMfWWiNONSMSA\n" + + "7m9y304QA0gKqlrFFn9U4hU89kv1IwIDAQABo4GYMIGVMA8GA1UdEwEB/wQFMAMB\n" + + "Af8wMgYIKwYBBQUHAQEEJjAkMCIGCCsGAQUFBzABhhZodHRwOi8vbG9jYWxob3N0\n" + + "OjM5MTM0MB8GA1UdIwQYMBaAFJNMsejEyJUB9tiWycVczvpiMVQZMB0GA1UdDgQW\n" + + "BBRhPnbmXAcIjgKa5azxrumhp4pEnjAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcN\n" + + "AQELBQADggEBAE4nOFdW9OirPnRvxihQXYL9CXLuGQz5tr0XgN8wSY6Un9b6CRiK\n" + + "7obgIGimVdhvUC1qdRcwJqgOfJ2/jR5/5Qo0TVp+ww4dHNdUoj73tagJ7jTu0ZMz\n" + + "5Zdp0uwd4RD/syvTeVcbPc3m4awtgEvRgzpDMcSeKPZWInlo7fbnowKSAUAfO8de\n" + + "0cDkxEBkzPIzGNu256cdLZOqOK9wLJ9mQ0zKgi/2NsldNc2pl/6jkGpA6uL5lJsm\n" + + "fo9sDusWNHV1YggqjDQ19hrf40VuuC9GFl/qAW3marMuEzY/NiKVUxty1q1s48SO\n" + + "g5LoEPDDkbygOt7ICL3HYG1VufhC1Q2YY9c=\n" + + "-----END CERTIFICATE-----"), + // Subject: CN=Root CA Cert, O=SomeCompany + // Issuer: CN=Root CA Cert, O=SomeCompany + // Validity: Fri Jul 08 14:37:18 PDT 2016 to Fri Jun 28 14:37:18 PDT 2019 + ROOT_CA("1", + "CN=Root CA Cert, O=SomeCompany", + "CN=Root CA Cert, O=SomeCompany", + -1299818863, + "-----BEGIN CERTIFICATE-----\n" + + "MIIDODCCAiCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAtMRQwEgYDVQQKEwtTb21l\n" + + "Q29tcGFueTEVMBMGA1UEAxMMUm9vdCBDQSBDZXJ0MB4XDTE2MDcwODIxMzcxOFoX\n" + + "DTE5MDYyODIxMzcxOFowLTEUMBIGA1UEChMLU29tZUNvbXBhbnkxFTATBgNVBAMT\n" + + "DFJvb3QgQ0EgQ2VydDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIlN\n" + + "M3WYEqkU2elXEZrV9QSDbDKwyaLEHafLFciH8Edoag3q/7jEzFJxI7JZ831tdbWQ\n" + + "Bm6Hgo+8pvetOFW1BckL8eIjyOONP2CKfFaeMaozsWi1cgxa+rjpU/Rekc+zBqvv\n" + + "y4Sr97TwT6nQiLlgjC1nCfR1SVpO51qoDChS7n785rsKEZxw/p+kkVWSZffU7zN9\n" + + "c645cPg//L/kjiyeKMkaquGQOYS68gQgy8YZXQv1E3l/8e8Ci1s1DYA5wpCbaBqg\n" + + "Tw84Rr4zlUEQBgXzQlRt+mPzeaDpdG1EeGkXrcdkZ+0EMELoOVXOEn6VNsz6vT3I\n" + + "KrnvQBSnN06xq/iWwC0CAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME\n" + + "GDAWgBSTTLHoxMiVAfbYlsnFXM76YjFUGTAdBgNVHQ4EFgQUk0yx6MTIlQH22JbJ\n" + + "xVzO+mIxVBkwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IBAQAAi+Nl\n" + + "sxP9t2IhiZIHRJGSBZuQlXIjwYIwbq3ZWc/ApZ+0oxtl7DYQi5uRNt8/opcGNCHc\n" + + "IY0fG93SbkDubXbxPYBW6D/RUjbz59ZryaP5ym55p1MjHTOqy+AM8g41xNTJikc3\n" + + "UUFXXnckeFbawijCsb7vf71owzKuxgBXi9n1rmXXtncKoA/LrUVXoUlKefdgDnsU\n" + + "sl3Q29eibE3HSqziMMoAOLm0jjekFGWIgLeTtyRYR1d0dNaUwsHTrQpPjxxUTn1x\n" + + "sAPpXKfzPnsYAZeeiaaE75GwbWlHzrNinvxdZQd0zctpfBJfVqD/+lWANlw+rOaK\n" + + "J2GyCaJINsyaI/I2\n" + + "-----END CERTIFICATE-----"); + + public String serialNumber; + public String algorithm; + public String subject; + public String issuer; + public String keyType; + public long certId; + public int keyLength; + public String encoded; + + TestCertificate(String serialNumber, String subject, String issuer, + long certId, String encoded) { + this.serialNumber = serialNumber; + this.subject = subject; + this.issuer = issuer; + this.algorithm = "SHA256withRSA"; + this.encoded = encoded; + this.certId = certId; + this.keyType = "RSA"; + this.keyLength = 2048; + } + + public X509Certificate generate(CertificateFactory cf) throws CertificateException { + ByteArrayInputStream is = new ByteArrayInputStream(encoded.getBytes()); + return (X509Certificate) cf.generateCertificate(is); + } + + public static void generateChain(boolean selfSignedTest) throws Exception { + // Do path validation as if it is always Tue, 06 Sep 2016 22:12:21 GMT + // This value is within the lifetimes of all certificates. + Date testDate = new Date(1473199941000L); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate c1 = TestCertificate.ONE.generate(cf); + X509Certificate c2 = TestCertificate.TWO.generate(cf); + X509Certificate ca = TestCertificate.ROOT_CA.generate(cf); + + TrustAnchor ta = new TrustAnchor(ca, null); + CertPathValidator validator = CertPathValidator.getInstance("PKIX"); + + PKIXParameters params = new PKIXParameters(Collections.singleton(ta)); + params.setRevocationEnabled(false); + params.setDate(testDate); + if (!selfSignedTest) { + CertPath path = cf.generateCertPath(List.of(c1, c2)); + validator.validate(path, params); + } else { + CertPath path = cf.generateCertPath(List.of(ca)); + validator.validate(path, params); + } + } +} \ No newline at end of file diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/security/TestTLSHandshake.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/security/TestTLSHandshake.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,70 @@ +/* + * 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 jdk.test.lib.security; + +import java.io.*; + +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; + + +public final class TestTLSHandshake extends SSLSocketTest { + + public static final String CIPHER_SUITE = + "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"; + public static final long HASHCODE = -1057291798L; + public static final long ANCHOR_HASHCODE = 1688661792L; + public static final String CERT_SERIAL = "edbec8f705af2514"; + public static final String ANCHOR_CERT_SERIAL = "8e191778b2f331be"; + + public String protocolVersion; + public String peerHost; + public int peerPort; + + @Override + protected void runServerApplication(SSLSocket socket) throws Exception { + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + } + + @Override + protected void runClientApplication(SSLSocket socket) throws Exception { + socket.setEnabledCipherSuites(new String[] { CIPHER_SUITE }); + InputStream sslIS = socket.getInputStream(); + OutputStream sslOS = socket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + SSLSession sslSession = socket.getSession(); + protocolVersion = sslSession.getProtocol(); + peerHost = sslSession.getPeerHost(); + peerPort = sslSession.getPeerPort(); + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/thread/ProcessThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/thread/ProcessThread.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,216 @@ +/* + * 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 jdk.test.lib.thread; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.io.PrintWriter; + +import java.util.concurrent.CountDownLatch; +import java.util.function.Predicate; + +/** + * The helper class for starting and stopping {@link Process} in a separate thread. + */ +public class ProcessThread extends TestThread { + + /** + * Creates a new {@code ProcessThread} object. + * + * @param threadName The name of thread + * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder} + */ + public ProcessThread(String threadName, String... cmd) { + super(new ProcessRunnable(new ProcessBuilder(cmd)), threadName); + } + + /** + * Creates a new {@code ProcessThread} object. + * + * @param threadName The name of thread. + * @param pb The ProcessBuilder to execute. + */ + public ProcessThread(String threadName, ProcessBuilder pb) { + super(new ProcessRunnable(pb), threadName); + } + + + /** + * Creates a new {@code ProcessThread} object. + * + * @param threadName The name of thread + * @param waitfor A predicate to determine whether the target process has been initialized + * @param cmd The string array of program and its arguments to pass to {@link ProcessBuilder} + */ + public ProcessThread(String threadName, Predicate waitfor, String... cmd) { + super(new ProcessRunnable(new ProcessBuilder(cmd), threadName, waitfor), threadName); + } + + /** + * Creates a new {@code ProcessThread} object. + * + * @param threadName The name of thread. + * @param waitfor A predicate to determine whether the target process has been initialized + * @param pb The ProcessBuilder to execute. + */ + public ProcessThread(String threadName, Predicate waitfor, ProcessBuilder pb) { + super(new ProcessRunnable(pb, threadName, waitfor), threadName); + } + + /** + * Stops {@link Process} started by {@code ProcessRunnable}. + * + * @throws InterruptedException + */ + public void stopProcess() throws InterruptedException { + ((ProcessRunnable) getRunnable()).stopProcess(); + } + + /** + * @return The process output, or null if the process has not yet completed. + */ + public OutputAnalyzer getOutput() { + return ((ProcessRunnable) getRunnable()).getOutput(); + } + + /** + * Returns the PID associated with this process thread + * @return The PID associated with this process thread + */ + public long getPid() throws InterruptedException { + return ((ProcessRunnable)getRunnable()).getPid(); + } + + public void sendMessage(String message) throws InterruptedException { + ((ProcessRunnable)getRunnable()).sendMessage(message); + } + + /** + * {@link Runnable} interface for starting and stopping {@link Process}. + */ + static class ProcessRunnable extends XRun { + + private final ProcessBuilder processBuilder; + private final CountDownLatch latch; + private volatile Process process; + private volatile OutputAnalyzer output; + private final Predicate waitfor; + private final String name; + + /** + * Creates a new {@code ProcessRunnable} object. + * + * @param pb The {@link ProcessBuilder} to run. + */ + public ProcessRunnable(ProcessBuilder pb) { + this(pb, "", null); + } + + /** + * Creates a new {@code ProcessRunnable} object. + * + * @param pb The {@link ProcessBuilder} to run. + * @param name An optional process name; may be null + * @param waitfor A predicate to determine whether the target process has been initialized; may be null + */ + public ProcessRunnable(ProcessBuilder pb, String name, Predicate waitfor) { + this.processBuilder = pb; + this.latch = new CountDownLatch(1); + this.name = name; + this.waitfor = waitfor; + } + + /** + * Starts the process in {@code ProcessThread}. + * All exceptions which occurs here will be caught and stored in {@code ProcessThread}. + * + * see {@link XRun} + */ + @Override + public void xrun() throws Throwable { + this.process = ProcessTools.startProcess(name, processBuilder, waitfor); + // Release when process is started + latch.countDown(); + + // Will block... + try { + this.process.waitFor(); + output = new OutputAnalyzer(this.process); + } catch (Throwable t) { + String name = Thread.currentThread().getName(); + System.out.println(String.format("ProcessThread[%s] failed: %s", name, t.toString())); + throw t; + } finally { + this.process.destroyForcibly().waitFor(); + String logMsg = ProcessTools.getProcessLog(processBuilder, output); + System.out.println(logMsg); + } + } + + /** + * Stops the process. + * + * @throws InterruptedException + */ + public void stopProcess() throws InterruptedException { + // Wait until process is started + latch.await(); + if (this.process != null) { + System.out.println("ProcessThread.stopProcess() will kill process"); + this.process.destroy(); + } + } + + /** + * Returns the OutputAnalyzer with stdout/stderr from the process. + * @return The process output, or null if process not completed. + * @throws InterruptedException + */ + public OutputAnalyzer getOutput() { + return output; + } + + /** + * Returns the PID associated with this process runnable + * @return The PID associated with this process runnable + */ + public long getPid() throws InterruptedException { + return getProcess().pid(); + } + + public void sendMessage(String message) throws InterruptedException { + try (PrintWriter pw = new PrintWriter(this.getProcess().getOutputStream())) { + pw.println(message); + pw.flush(); + } + } + + private Process getProcess() throws InterruptedException { + latch.await(); + return process; + } + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/thread/TestThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/thread/TestThread.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.thread; + +import java.util.concurrent.TimeoutException; + +/** + * Thread which catches exceptions thrown during the execution + * and stores them for later analysis. + * + *
+ * {@code
+ * TestThread thread = new TestThread(new XRun() {
+ *      public void run() {
+ *      // do something
+ *      }
+ * });
+ * thread.start();
+ * // do something
+ * Throwable uncaught = thread.getUncaught();
+ * }
+ * 
+ */ +public class TestThread extends Thread { + + private final Runnable runnable; + private volatile Throwable uncaught; + + /** + * Returns {@link Runnable} the thread has been created with. + * + * @return The object whose {@code run} method is called + */ + public Runnable getRunnable() { + return runnable; + } + + /** + * Creates a new {@code TestThread} object. + * + * @param target The object whose {@code run} method is called + * @param name The thread name + */ + public TestThread(Runnable target, String name) { + super(target, name); + this.runnable = target; + } + + /** + * Creates a new {@code TestThread} object. + * + * @param target The object whose {@code run} method is called + */ + public TestThread(Runnable target) { + super(target); + this.runnable = target; + } + + /** + * Creates a new {@code TestThread} object. + * + * @param group The thread group + * @param target The object whose {@code run} method is called + * @param name The thread name + * @param stackSize Stack size + */ + public TestThread(ThreadGroup group, Runnable target, String name, + long stackSize) { + super(group, target, name, stackSize); + this.runnable = target; + } + + /** + * Creates a new {@code TestThread} object. + * + * @param group The thread group + * @param target The object whose {@code run} method is called + * @param name The thread name + */ + public TestThread(ThreadGroup group, Runnable target, String name) { + super(group, target, name); + this.runnable = target; + } + + /** + * Creates a new {@code TestThread} object. + * + * @param group The thread group + * @param target The object whose {@code run} method is called + */ + public TestThread(ThreadGroup group, Runnable target) { + super(group, target); + this.runnable = target; + } + + /** + * The thread executor. + */ + @Override + public void run() { + try { + super.run(); + } catch (Throwable t) { + uncaught = t; + } + } + + /** + * Returns exception caught during the execution. + * + * @return {@link Throwable} + */ + public Throwable getUncaught() { + return uncaught; + } + + /** + * Waits for {@link TestThread} to die + * and throws exception caught during the execution. + * + * @throws InterruptedException + * @throws Throwable + */ + public void joinAndThrow() throws InterruptedException, Throwable { + join(); + if (uncaught != null) { + throw uncaught; + } + } + + /** + * Waits during {@code timeout} for {@link TestThread} to die + * and throws exception caught during the execution. + * + * @param timeout The time to wait in milliseconds + * @throws InterruptedException + * @throws Throwable + */ + public void joinAndThrow(long timeout) throws InterruptedException, + Throwable { + join(timeout); + if (isAlive()) { + throw new TimeoutException(); + } + if (uncaught != null) { + throw uncaught; + } + } + + /** + * Waits for {@link TestThread} to die + * and returns exception caught during the execution. + * + * @return Exception caught during the execution + * @throws InterruptedException + */ + public Throwable joinAndReturn() throws InterruptedException { + join(); + if (uncaught != null) { + return uncaught; + } + return null; + } + + /** + * Waits during {@code timeout} for {@link TestThread} to die + * and returns exception caught during the execution. + * + * @param timeout The time to wait in milliseconds + * @return Exception caught during the execution + * @throws InterruptedException + */ + public Throwable joinAndReturn(long timeout) throws InterruptedException { + join(timeout); + if (isAlive()) { + return new TimeoutException(); + } + if (uncaught != null) { + return uncaught; + } + return null; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/thread/XRun.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/thread/XRun.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.thread; + +/** + * This type serves no other purpose than to simply allow automatically running + * something in a thread, and have all exceptions propagated to + * RuntimeExceptions, which are thrown up to thread, which in turn should + * probably be a {@link TestThread} to they are stored. + */ +public abstract class XRun implements Runnable { + + /** + * Invokes {@code xrun()} and throws all exceptions caught in it + * up to the thread. + */ + public final void run() { + try { + xrun(); + } catch (Error e) { + throw e; + } catch (RuntimeException e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + + /** + * Override this method to implement what to run in the thread. + * + * @throws Throwable + */ + protected abstract void xrun() throws Throwable; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/FileUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/FileUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,286 @@ +/* + * 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. + */ + +package jdk.test.lib.util; + +import jdk.test.lib.Platform; + +import java.io.IOException; +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.lang.ProcessBuilder.Redirect; +import java.nio.file.DirectoryNotEmptyException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.time.Instant; +import java.time.Duration; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.ArrayDeque; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +/** + * Common library for various test file utility functions. + */ +public final class FileUtils { + private static final boolean IS_WINDOWS = Platform.isWindows(); + private static final int RETRY_DELETE_MILLIS = IS_WINDOWS ? 500 : 0; + private static final int MAX_RETRY_DELETE_TIMES = IS_WINDOWS ? 15 : 0; + + /** + * Deletes a file, retrying if necessary. + * + * @param path the file to delete + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific exception) + * @throws IOException + * if an I/O error occurs + */ + public static void deleteFileWithRetry(Path path) throws IOException { + try { + deleteFileWithRetry0(path); + } catch (InterruptedException x) { + throw new IOException("Interrupted while deleting.", x); + } + } + + /** + * Deletes a file, retrying if necessary. + * No exception thrown if file doesn't exist. + * + * @param path the file to delete + * + * @throws NoSuchFileException + * if the file does not exist (optional specific exception) + * @throws DirectoryNotEmptyException + * if the file is a directory and could not otherwise be deleted + * because the directory is not empty (optional specific exception) + * @throws IOException + * if an I/O error occurs + */ + public static void deleteFileIfExistsWithRetry(Path path) throws IOException { + try { + if (Files.exists(path)) { + deleteFileWithRetry0(path); + } + } catch (InterruptedException x) { + throw new IOException("Interrupted while deleting.", x); + } + } + + private static void deleteFileWithRetry0(Path path) + throws IOException, InterruptedException { + int times = 0; + IOException ioe = null; + while (true) { + try { + Files.delete(path); + // Checks for absence of the file. Semantics of Files.exists() is not the same. + while (!Files.notExists(path)) { + times++; + if (times > MAX_RETRY_DELETE_TIMES) { + throw new IOException("File still exists after " + times + " waits."); + } + Thread.sleep(RETRY_DELETE_MILLIS); + } + break; + } catch (NoSuchFileException | DirectoryNotEmptyException x) { + throw x; + } catch (IOException x) { + // Backoff/retry in case another process is accessing the file + times++; + if (ioe == null) { + ioe = x; + } else { + ioe.addSuppressed(x); + } + + if (times > MAX_RETRY_DELETE_TIMES) { + throw ioe; + } + Thread.sleep(RETRY_DELETE_MILLIS); + } + } + } + + /** + * Deletes a directory and its subdirectories, retrying if necessary. + * + * @param dir the directory to delete + * + * @throws IOException + * If an I/O error occurs. Any such exceptions are caught + * internally. If only one is caught, then it is re-thrown. + * If more than one exception is caught, then the second and + * following exceptions are added as suppressed exceptions of the + * first one caught, which is then re-thrown. + */ + public static void deleteFileTreeWithRetry(Path dir) throws IOException { + IOException ioe = null; + final List excs = deleteFileTreeUnchecked(dir); + if (!excs.isEmpty()) { + ioe = excs.remove(0); + for (IOException x : excs) { + ioe.addSuppressed(x); + } + } + if (ioe != null) { + throw ioe; + } + } + + public static List deleteFileTreeUnchecked(Path dir) { + final List excs = new ArrayList<>(); + try { + java.nio.file.Files.walkFileTree(dir, new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + try { + deleteFileWithRetry0(file); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + excs.add(new IOException("Interrupted while deleting.", x)); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + try { + deleteFileWithRetry0(dir); + } catch (IOException x) { + excs.add(x); + } catch (InterruptedException x) { + excs.add(new IOException("Interrupted while deleting.", x)); + return FileVisitResult.TERMINATE; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + excs.add(exc); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException x) { + excs.add(x); + } + return excs; + } + + /** + * Checks whether all file systems are accessible. This is performed + * by checking free disk space on all mounted file systems via a + * separate, spawned process. File systems are considered to be + * accessible if this process completes successfully before a given + * fixed duration has elapsed. + * + * @implNote On Unix this executes the {@code df} command in a separate + * process and on Windows always returns {@code true}. + */ + public static boolean areFileSystemsAccessible() throws IOException { + boolean areFileSystemsAccessible = true; + if (!IS_WINDOWS) { + // try to check whether 'df' hangs + System.out.println("\n--- df output ---"); + System.out.flush(); + Process proc = new ProcessBuilder("df").inheritIO().start(); + try { + proc.waitFor(90, TimeUnit.SECONDS); + } catch (InterruptedException ignored) { + } + try { + int exitValue = proc.exitValue(); + if (exitValue != 0) { + System.err.printf("df process exited with %d != 0%n", + exitValue); + areFileSystemsAccessible = false; + } + } catch (IllegalThreadStateException ignored) { + System.err.println("df command apparently hung"); + areFileSystemsAccessible = false; + } + } + return areFileSystemsAccessible; + } + + /** + * List the open file descriptors (if supported by the 'lsof' command). + * @param ps a printStream to send the output to + * @throws UncheckedIOException if an error occurs + */ + public static void listFileDescriptors(PrintStream ps) { + + Optional lsof = Arrays.stream(lsCommands) + .filter(args -> Files.isExecutable(Path.of(args[0]))) + .findFirst(); + lsof.ifPresent(args -> { + try { + ps.printf("Open File Descriptors:%n"); + long pid = ProcessHandle.current().pid(); + ProcessBuilder pb = new ProcessBuilder(args[0], args[1], Integer.toString((int) pid)); + pb.redirectErrorStream(true); // combine stderr and stdout + pb.redirectOutput(Redirect.PIPE); + + Process p = pb.start(); + Instant start = Instant.now(); + p.getInputStream().transferTo(ps); + + try { + int timeout = 10; + if (!p.waitFor(timeout, TimeUnit.SECONDS)) { + System.out.printf("waitFor timed out: %d%n", timeout); + } + } catch (InterruptedException ie) { + throw new IOException("interrupted", ie); + } + ps.println(); + } catch (IOException ioe) { + throw new UncheckedIOException("error listing file descriptors", ioe); + } + }); + } + + // Possible command locations and arguments + static String[][] lsCommands = new String[][] { + {"/usr/bin/lsof", "-p"}, + {"/usr/sbin/lsof", "-p"}, + {"/bin/lsof", "-p"}, + {"/sbin/lsof", "-p"}, + {"/usr/local/bin/lsof", "-p"}, + {"/usr/bin/pfiles", "-F"}, // Solaris + }; +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/JarUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/JarUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * This class consists exclusively of static utility methods that are useful + * for creating and manipulating JAR files. + */ +public final class JarUtils { + private static final int DEFAULT_BUFFER_SIZE = 8192; + private JarUtils() { } + + /** + * Creates a JAR file. + * + * Equivalent to {@code jar cfm -C file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... files) + throws IOException + { + // create the target directory + Path parent = jarfile.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + + List entries = findAllRegularFiles(dir, files); + + try (OutputStream out = Files.newOutputStream(jarfile); + JarOutputStream jos = new JarOutputStream(out)) { + if (man != null) { + JarEntry je = new JarEntry(JarFile.MANIFEST_NAME); + jos.putNextEntry(je); + man.write(jos); + jos.closeEntry(); + } + + for (Path entry : entries) { + String name = toJarEntryName(entry); + jos.putNextEntry(new JarEntry(name)); + Files.copy(dir.resolve(entry), jos); + jos.closeEntry(); + } + } + } + + /** + * Creates a JAR file. + * + * Equivalent to {@code jar cf -C file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Path dir, Path... files) + throws IOException + { + createJarFile(jarfile, null, dir, files); + } + + /** + * Creates a JAR file from the contents of a directory. + * + * Equivalent to {@code jar cf -C .} + */ + public static void createJarFile(Path jarfile, Path dir) throws IOException { + createJarFile(jarfile, dir, Paths.get(".")); + } + + + /** + * Creates a JAR file. + * + * Equivalent to {@code jar cf -C file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void createJarFile(Path jarfile, Path dir, String... input) + throws IOException + { + Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new); + createJarFile(jarfile, dir, paths); + } + + /** + * Updates a JAR file. + * + * Equivalent to {@code jar uf -C file...} + * + * The input files are resolved against the given directory. Any input + * files that are directories are processed recursively. + */ + public static void updateJarFile(Path jarfile, Path dir, Path... files) + throws IOException + { + List entries = findAllRegularFiles(dir, files); + + Set names = entries.stream() + .map(JarUtils::toJarEntryName) + .collect(Collectors.toSet()); + + Path tmpfile = Files.createTempFile("jar", "jar"); + + try (OutputStream out = Files.newOutputStream(tmpfile); + JarOutputStream jos = new JarOutputStream(out)) { + // copy existing entries from the original JAR file + try (JarFile jf = new JarFile(jarfile.toString())) { + Enumeration jentries = jf.entries(); + while (jentries.hasMoreElements()) { + JarEntry jentry = jentries.nextElement(); + if (!names.contains(jentry.getName())) { + jos.putNextEntry(jentry); + transferTo(jf.getInputStream(jentry), jos); + } + } + } + + // add the new entries + for (Path entry : entries) { + String name = toJarEntryName(entry); + jos.putNextEntry(new JarEntry(name)); + Files.copy(dir.resolve(entry), jos); + } + } + + // replace the original JAR file + Files.move(tmpfile, jarfile, StandardCopyOption.REPLACE_EXISTING); + } + + /** + * Updates a JAR file. + * + * Equivalent to {@code jar uf -C .} + */ + public static void updateJarFile(Path jarfile, Path dir) throws IOException { + updateJarFile(jarfile, dir, Paths.get(".")); + } + + + /** + * Create jar file with specified files. If a specified file does not exist, + * a new jar entry will be created with the file name itself as the content. + */ + @Deprecated + public static void createJar(String dest, String... files) + throws IOException { + try (JarOutputStream jos = new JarOutputStream( + new FileOutputStream(dest), new Manifest())) { + for (String file : files) { + System.out.println(String.format("Adding %s to %s", + file, dest)); + + // add an archive entry, and write a file + jos.putNextEntry(new JarEntry(file)); + try (FileInputStream fis = new FileInputStream(file)) { + transferTo(fis, jos); + } catch (FileNotFoundException e) { + jos.write(file.getBytes()); + } + } + } + System.out.println(); + } + + /** + * Add or remove specified files to existing jar file. If a specified file + * to be updated or added does not exist, the jar entry will be created + * with the file name itself as the content. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param files the files to update. The list is broken into 2 groups + * by a "-" string. The files before in the 1st group will + * be either updated or added. The files in the 2nd group + * will be removed. If no "-" exists, all files belong to + * the 1st group. + * @throws IOException if there is an error + */ + @Deprecated + public static void updateJar(String src, String dest, String... files) + throws IOException { + Map changes = new HashMap<>(); + boolean update = true; + for (String file : files) { + if (file.equals("-")) { + update = false; + } else if (update) { + try { + Path p = Paths.get(file); + if (Files.exists(p)) { + changes.put(file, p); + } else { + changes.put(file, file); + } + } catch (InvalidPathException e) { + // Fallback if file not a valid Path. + changes.put(file, file); + } + } else { + changes.put(file, Boolean.FALSE); + } + } + updateJar(src, dest, changes); + } + + /** + * Update content of a jar file. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param changes a map of changes, key is jar entry name, value is content. + * Value can be Path, byte[] or String. If key exists in + * src but value is Boolean FALSE. The entry is removed. + * Existing entries in src not a key is unmodified. + * @throws IOException if there is an error + */ + @Deprecated + public static void updateJar(String src, String dest, + Map changes) + throws IOException { + + // What if input changes is immutable? + changes = new HashMap<>(changes); + + System.out.printf("Creating %s from %s...\n", dest, src); + + if (dest.equals(src)) { + throw new IOException("src and dest cannot be the same"); + } + + try (JarOutputStream jos = new JarOutputStream( + new FileOutputStream(dest))) { + + try (JarFile srcJarFile = new JarFile(src)) { + Enumeration entries = srcJarFile.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if (changes.containsKey(name)) { + System.out.println(String.format("- Update %s", name)); + updateEntry(jos, name, changes.get(name)); + changes.remove(name); + } else { + System.out.println(String.format("- Copy %s", name)); + jos.putNextEntry(entry); + transferTo(srcJarFile.getInputStream(entry), jos); + } + } + } + for (Map.Entry e : changes.entrySet()) { + System.out.println(String.format("- Add %s", e.getKey())); + updateEntry(jos, e.getKey(), e.getValue()); + } + } + System.out.println(); + } + + /** + * Update the Manifest inside a jar. + * + * @param src the original jar file name + * @param dest the new jar file name + * @param man the Manifest + * + * @throws IOException + */ + public static void updateManifest(String src, String dest, Manifest man) + throws IOException { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + man.write(bout); + + Map manifest = new HashMap<>(); + manifest.put(JarFile.MANIFEST_NAME, bout.toByteArray()); + updateJar(src, dest, manifest); + } + + private static void updateEntry(JarOutputStream jos, String name, Object content) + throws IOException { + if (content instanceof Boolean) { + if (((Boolean) content).booleanValue()) { + throw new RuntimeException("Boolean value must be FALSE"); + } + } else { + jos.putNextEntry(new JarEntry(name)); + if (content instanceof Path) { + transferTo(Files.newInputStream((Path) content), jos); + } else if (content instanceof byte[]) { + jos.write((byte[]) content); + } else if (content instanceof String) { + jos.write(((String) content).getBytes()); + } else { + throw new RuntimeException("Unknown type " + content.getClass()); + } + } + } + + /** + * Maps a file path to the equivalent name in a JAR file + */ + private static String toJarEntryName(Path file) { + Path normalized = file.normalize(); + return normalized.subpath(0, normalized.getNameCount()) // drop root + .toString() + .replace(File.separatorChar, '/'); + } + + private static List findAllRegularFiles(Path dir, Path[] files) throws IOException { + List entries = new ArrayList<>(); + for (Path file : files) { + try (Stream stream = Files.find(dir.resolve(file), Integer.MAX_VALUE, + (p, attrs) -> attrs.isRegularFile())) { + stream.map(dir::relativize) + .forEach(entries::add); + } + } + return entries; + } + + public static long transferTo(InputStream in , OutputStream out) throws IOException { + //Objects.requireNonNull(out, "out"); + long transferred = 0; + byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; + int read; + while ((read = in.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) { + out.write(buffer, 0, read); + transferred += read; + } + return transferred; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/ModuleUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/ModuleUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.net.URI; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + + +/** + * This class consists exclusively of static utility methods that are useful + * for creating tests for modules. + */ + +public final class ModuleUtils { + private ModuleUtils() { } + + + /** + * Returns a ModuleFinder that finds modules with the given module + * descriptors. + */ + public static ModuleFinder finderOf(ModuleDescriptor... descriptors) { + + // Create a ModuleReference for each module + Map namesToReference = new HashMap<>(); + + for (ModuleDescriptor descriptor : descriptors) { + String name = descriptor.name(); + + URI uri = URI.create("module:/" + name); + + ModuleReference mref = new ModuleReference(descriptor, uri) { + @Override + public ModuleReader open() { + throw new UnsupportedOperationException(); + } + }; + + namesToReference.put(name, mref); + } + + return new ModuleFinder() { + @Override + public Optional find(String name) { + Objects.requireNonNull(name); + return Optional.ofNullable(namesToReference.get(name)); + } + @Override + public Set findAll() { + return new HashSet<>(namesToReference.values()); + } + }; + } + +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/OptimalCapacity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/OptimalCapacity.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; + +/** + * Utility functions to check that the static storages are pre-sized + * optimally. + */ +public final class OptimalCapacity { + + private OptimalCapacity() {} + + /** + * Checks adequacy of the initial capacity of a static field + * of type {@code ArrayList}. + * + * Having + *
+     * class XClass {
+     *     static ArrayList theList = new ArrayList(N);
+     * }
+     * 
+ * + * you should call from the test + * + *
+     * OptimalCapacity.assertProperlySized(XClass.class, "theList", N);
+     * 
+ */ + public static void ofArrayList(Class clazz, String fieldName, + int initialCapacity) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (!ArrayList.class.equals(obj.getClass())) { + throw new RuntimeException("'" + field + + "' expected to be of type ArrayList"); + } + ArrayList list = (ArrayList)obj; + + // For ArrayList the optimal capacity is its final size + if (list.size() != initialCapacity) { + throw new RuntimeException("Size of '" + field + + "' is " + list.size() + + ", but expected to be " + initialCapacity); + } + if (internalArraySize(list) != initialCapacity) { + throw new RuntimeException("Capacity of '" + field + + "' is " + internalArraySize(list) + + ", but expected to be " + initialCapacity); + } + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Checks adequacy of the initial capacity of a static field + * of type {@code HashMap}. + * + * Having + *
+     * class XClass {
+     *     static HashMap theMap = new HashMap(N);
+     * }
+     * 
+ * + * you should call from the test + * + *
+     * OptimalCapacity.ofHashMap(XClass.class, "theMap", N);
+     * 
+ */ + public static void ofHashMap(Class clazz, String fieldName, + int initialCapacity) + { + ofHashMap(clazz, null, fieldName, initialCapacity); + } + + /** + * Checks adequacy of the initial capacity of a non-static field + * of type {@code HashMap}. + * + * Having + *
+     * class XClass {
+     *     HashMap theMap = new HashMap(N);
+     * }
+     * XClass instance = ...
+     * 
+ * + * you should call from the test + * + *
+     * OptimalCapacity.ofHashMap(XClass.class, instance, "theMap", N);
+     * 
+ */ + public static void ofHashMap(Class clazz, Object instance, + String fieldName, int initialCapacity) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(instance); + if (!HashMap.class.equals(obj.getClass())) { + throw new RuntimeException(field + + " expected to be of type HashMap"); + } + HashMap map = (HashMap)obj; + + // Check that the map allocates only necessary amount of space + HashMap tmp = new HashMap<>(map); + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Final capacity of '" + field + + "' is " + internalArraySize(map) + + ", which exceeds necessary minimum " + internalArraySize(tmp)); + } + + // Check that map is initially properly sized + tmp = new HashMap<>(initialCapacity); + tmp.put(new Object(), new Object()); // trigger storage init + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Requested capacity of '" + field + + "' was " + initialCapacity + + ", which resulted in final capacity " + internalArraySize(tmp) + + ", which differs from necessary minimum " + internalArraySize(map)); + } + + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Checks adequacy of the expected maximum size of a static field + * of type {@code IdentityHashMap}. + * + * Having + *
+     * class XClass {
+     *     static IdentityHashMap theMap = new IdentityHashMap(M);
+     * }
+     * 
+ * + * you should call from the test + * + *
+     * OptimalCapacity.ofIdentityHashMap(XClass.class, "theMap", M);
+     * 
+ */ + public static void ofIdentityHashMap(Class clazz, String fieldName, + int expectedMaxSize) + { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + Object obj = field.get(null); + if (!IdentityHashMap.class.equals(obj.getClass())) { + throw new RuntimeException("'" + field + + "' expected to be of type IdentityHashMap"); + } + IdentityHashMap map = (IdentityHashMap)obj; + + // Check that size of map is what was expected + if (map.size() != expectedMaxSize) { + throw new RuntimeException("Size of '" + field + + "' is " + map.size() + + ", which differs from expected " + expectedMaxSize); + } + + // Check that the map allocated only necessary amount of memory + IdentityHashMap tmp = new IdentityHashMap<>(map); + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Final capacity of '" + field + + "' is " + internalArraySize(map) + + ", which exceeds necessary minimum " + internalArraySize(tmp)); + } + + // Check that map was initially properly sized + tmp = new IdentityHashMap<>(expectedMaxSize); + tmp.put(new Object(), new Object()); // trigger storage init + if (internalArraySize(map) != internalArraySize(tmp)) { + throw new RuntimeException("Requested number of elements in '" + field + + "' was " + expectedMaxSize + + ", which resulted in final capacity " + internalArraySize(tmp) + + ", which differs from necessary minimum " + internalArraySize(map)); + } + } catch (ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + + /** + * Returns size of the internal storage. + */ + private static int internalArraySize(Object container) + throws ReflectiveOperationException { + Field field; + if (ArrayList.class.equals(container.getClass())) { + field = ArrayList.class.getDeclaredField("elementData"); + } else if (HashMap.class.equals(container.getClass())) { + field = HashMap.class.getDeclaredField("table"); + } else if (IdentityHashMap.class.equals(container.getClass())) { + field = IdentityHashMap.class.getDeclaredField("table"); + } else { + throw new RuntimeException("Unexpected class " + + container.getClass()); + } + field.setAccessible(true); + return ((Object[])field.get(container)).length; + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/Pair.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/Pair.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.util.Objects; + +/** + * Pair - a two element tuple + * + * @param first type + * @param second type + */ +public class Pair { + public final F first; + public final S second; + + public Pair(F first, S second) { + this.first = first; + this.second = second; + } + + @Override + public String toString() { + return "(" + first + ":" + second + ")"; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Pair) { + Pair otherPair = (Pair) other; + return Objects.equals(first, otherPair.first) && + Objects.equals(second, otherPair.second); + } + return false; + } + + @Override + public int hashCode() { + if (first == null) { + return (second == null) ? 0 : second.hashCode(); + } else if (second == null) { + return first.hashCode(); + } else { + return first.hashCode() * 17 + second.hashCode(); + } + } +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/SerializationUtils.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/SerializationUtils.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Common library for various test serialization utility functions. + */ +public final class SerializationUtils { + /** + * Serialize an object into byte array. + */ + public static byte[] serialize(Object obj) throws IOException { + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + try (ObjectOutputStream out = new ObjectOutputStream(bs)) { + out.writeObject(obj); + } + return bs.toByteArray(); + } + + /** + * Deserialize an object from byte array. + */ + public static Object deserialize(byte[] ba) throws IOException, ClassNotFoundException { + try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba))) { + return in.readObject(); + } + } + private SerializationUtils() {} +} diff -r 5b3afcfc9926 test/test/lib/jdk/test/lib/util/Triple.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jdk/test/lib/util/Triple.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib.util; + +import java.util.Objects; + +/** + * Triple - a three element tuple + * + * @param first element type + * @param second element type + * @param third element type + */ +public class Triple { + private final Pair> container; + + /** + * Constructor + * + * @param first first element of the triple + * @param second second element of the triple + * @param third third element of the triple + */ + public Triple(F first, S second, T third) { + container = new Pair<>(first, new Pair<>(second, third)); + } + + /** + * Gets first element of the triple + */ + public F getFirst() { + return container.first; + } + + /** + * Gets second element of the triple + */ + public S getSecond() { + return container.second.first; + } + + /** + * Gets third element of the triple + */ + public T getThird() { + return container.second.second; + } + + @Override + public int hashCode() { + return container.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Triple) { + Triple objTriple = (Triple) obj; + return Objects.equals(container.first, objTriple.container.first) + && Objects.equals(container.second, + objTriple.container.second); + } + return false; + } + + @Override + public String toString() { + return "(" + getFirst() + " : " + getSecond() + " : " + getThird() + ")"; + } +} diff -r 5b3afcfc9926 test/test/lib/jtreg/SkippedException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/jtreg/SkippedException.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,38 @@ +/* + * 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 jtreg; + +/** + * {@code SkippedException} is an exception treated by jtreg as an indication + * of skipped status. + */ +public final class SkippedException extends RuntimeException { + public SkippedException(String s, Throwable t) { + super(s, t); + } + + public SkippedException(String s) { + super(s); + } +} diff -r 5b3afcfc9926 test/test/lib/sun/hotspot/WhiteBox.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/sun/hotspot/WhiteBox.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.hotspot; + +import java.lang.management.MemoryUsage; +import java.lang.reflect.Executable; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Stream; +import java.security.BasicPermission; +import java.net.URL; + +import sun.hotspot.parser.DiagnosticCommand; + +public class WhiteBox { + + @SuppressWarnings("serial") + public static class WhiteBoxPermission extends BasicPermission { + public WhiteBoxPermission(String s) { + super(s); + } + } + + private WhiteBox() {} + private static final WhiteBox instance = new WhiteBox(); + private static native void registerNatives(); + + /** + * Returns the singleton WhiteBox instance. + * + * The returned WhiteBox object should be carefully guarded + * by the caller, since it can be used to read and write data + * at arbitrary memory addresses. It must never be passed to + * untrusted code. + */ + public synchronized static WhiteBox getWhiteBox() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new WhiteBoxPermission("getInstance")); + } + return instance; + } + + static { + registerNatives(); + } + + // Get the maximum heap size supporting COOPs + public native long getCompressedOopsMaxHeapSize(); + // Arguments + public native void printHeapSizes(); + + // Memory + public native long getObjectAddress(Object o); + public native int getHeapOopSize(); + public native int getVMPageSize(); + public native long getVMLargePageSize(); + + public native boolean isObjectInOldGen(Object o); + public native long getObjectSize(Object o); + + // Runtime + // Make sure class name is in the correct format + public boolean isClassAlive(String name) { + return isClassAlive0(name.replace('.', '/')); + } + private native boolean isClassAlive0(String name); + public native boolean isMonitorInflated(Object obj); + public native void forceSafepoint(); + + // Resource/Class Lookup Cache + public native boolean classKnownToNotExist(ClassLoader loader, String name); + public native URL[] getLookupCacheURLs(ClassLoader loader); + public native int[] getLookupCacheMatches(ClassLoader loader, String name); + + // JVMTI + public native void addToBootstrapClassLoaderSearch(String segment); + public native void addToSystemClassLoaderSearch(String segment); + + // G1 + public native boolean g1InConcurrentMark(); + public native boolean g1IsHumongous(Object o); + public native long g1NumMaxRegions(); + public native long g1NumFreeRegions(); + public native int g1RegionSize(); + public native MemoryUsage g1AuxiliaryMemoryUsage(); + public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native long NMTMalloc(long size); + public native void NMTFree(long mem); + public native long NMTReserveMemory(long size); + public native void NMTCommitMemory(long addr, long size); + public native void NMTUncommitMemory(long addr, long size); + public native void NMTReleaseMemory(long addr, long size); + public native long NMTMallocWithPseudoStack(long size, int index); + public native long NMTMallocWithPseudoStackAndType(long size, int index, int type); + public native boolean NMTIsDetailSupported(); + public native boolean NMTChangeTrackingLevel(); + public native int NMTGetHashSize(); + + // Compiler + public native void deoptimizeAll(); + public boolean isMethodCompiled(Executable method) { + return isMethodCompiled(method, false /*not osr*/); + } + public native boolean isMethodCompiled(Executable method, boolean isOsr); + public boolean isMethodCompilable(Executable method) { + return isMethodCompilable(method, -1 /*any*/); + } + public boolean isMethodCompilable(Executable method, int compLevel) { + return isMethodCompilable(method, compLevel, false /*not osr*/); + } + public native boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr); + public native boolean isMethodQueuedForCompilation(Executable method); + public int deoptimizeMethod(Executable method) { + return deoptimizeMethod(method, false /*not osr*/); + } + public native int deoptimizeMethod(Executable method, boolean isOsr); + public void makeMethodNotCompilable(Executable method) { + makeMethodNotCompilable(method, -1 /*any*/); + } + public void makeMethodNotCompilable(Executable method, int compLevel) { + makeMethodNotCompilable(method, compLevel, false /*not osr*/); + } + public native void makeMethodNotCompilable(Executable method, int compLevel, boolean isOsr); + public int getMethodCompilationLevel(Executable method) { + return getMethodCompilationLevel(method, false /*not ost*/); + } + public native int getMethodCompilationLevel(Executable method, boolean isOsr); + public native boolean testSetDontInlineMethod(Executable method, boolean value); + public int getCompileQueuesSize() { + return getCompileQueueSize(-1 /*any*/); + } + public native int getCompileQueueSize(int compLevel); + public native boolean testSetForceInlineMethod(Executable method, boolean value); + public boolean enqueueMethodForCompilation(Executable method, int compLevel) { + return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/); + } + public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci); + public native void clearMethodState(Executable method); + public native void markMethodProfiled(Executable method); + public native int getMethodEntryBci(Executable method); + public native Object[] getNMethod(Executable method, boolean isOsr); + + // Intered strings + public native boolean isInStringTable(String str); + + // Memory + public native void readReservedMemory(); + public native long allocateMetaspace(ClassLoader classLoader, long size); + public native void freeMetaspace(ClassLoader classLoader, long addr, long size); + public native long incMetaspaceCapacityUntilGC(long increment); + public native long metaspaceCapacityUntilGC(); + + // Force Young GC + public native void youngGC(); + + // Force Full GC + public native void fullGC(); + + // Method tries to start concurrent mark cycle. + // It returns false if CM Thread is always in concurrent cycle. + public native boolean g1StartConcMarkCycle(); + + // Tests on ReservedSpace/VirtualSpace classes + public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations); + public native void runMemoryUnitTests(); + public native void readFromNoaccessArea(); + public native long getThreadStackSize(); + public native long getThreadRemainingStackSize(); + + // CPU features + public native String getCPUFeatures(); + + // Native extensions + public native long getHeapUsageForContext(int context); + public native long getHeapRegionCountForContext(int context); + public native int getContextForObject(Object obj); + public native void printRegionInfo(int context); + + // VM flags + public native void setBooleanVMFlag(String name, boolean value); + public native void setIntxVMFlag(String name, long value); + public native void setUintxVMFlag(String name, long value); + public native void setUint64VMFlag(String name, long value); + public native void setStringVMFlag(String name, String value); + public native void setDoubleVMFlag(String name, double value); + public native Boolean getBooleanVMFlag(String name); + public native Long getIntxVMFlag(String name); + public native Long getUintxVMFlag(String name); + public native Long getUint64VMFlag(String name); + public native String getStringVMFlag(String name); + public native Double getDoubleVMFlag(String name); + private final List> flagsGetters = Arrays.asList( + this::getBooleanVMFlag, this::getIntxVMFlag, this::getUintxVMFlag, + this::getUint64VMFlag, this::getStringVMFlag, this::getDoubleVMFlag); + + public Object getVMFlag(String name) { + return flagsGetters.stream() + .map(f -> f.apply(name)) + .filter(x -> x != null) + .findAny() + .orElse(null); + } + public native int getOffsetForName0(String name); + public int getOffsetForName(String name) throws Exception { + int offset = getOffsetForName0(name); + if (offset == -1) { + throw new RuntimeException(name + " not found"); + } + return offset; + } + + // Class Data Sharing + public native boolean isSharedClass(Class c); + + // Returns true on linux if library has the noexecstack flag set. + public native boolean checkLibSpecifiesNoexecstack(String libfilename); + + // Container testing + public native boolean isContainerized(); + public native void printOsInfo(); + +} diff -r 5b3afcfc9926 test/test/lib/sun/hotspot/code/NMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/sun/hotspot/code/NMethod.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.hotspot.code; + +import java.lang.reflect.Executable; +import sun.hotspot.WhiteBox; + +public class NMethod { + private static final WhiteBox wb = WhiteBox.getWhiteBox(); + public static NMethod get(Executable method, boolean isOsr) { + Object[] obj = wb.getNMethod(method, isOsr); + return obj == null ? null : new NMethod(obj); + } + private NMethod(Object[] obj) { + assert obj.length == 3; + comp_level = (Integer) obj[0]; + compile_id = (Integer) obj[1]; + insts = (byte[]) obj[2]; + } + public final byte[] insts; + public final int comp_level; + public final int compile_id; + + @Override + public String toString() { + return "NMethod{" + + "insts=" + insts + + ", comp_level=" + comp_level + + ", compile_id=" + compile_id + + '}'; + } +} diff -r 5b3afcfc9926 test/test/lib/sun/hotspot/cpuinfo/CPUInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/sun/hotspot/cpuinfo/CPUInfo.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.hotspot.cpuinfo; + +import java.util.List; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +import sun.hotspot.WhiteBox; + +/** + * Information about CPU on test box. + * + * CPUInfo uses WhiteBox to gather information, + * so WhiteBox class should be added to bootclasspath + * and option -XX:+WhiteBoxAPI should expclicetly + * specified on command line. + */ +public class CPUInfo { + + private static final List features; + private static final String additionalCPUInfo; + + static { + WhiteBox wb = WhiteBox.getWhiteBox(); + + Pattern additionalCPUInfoRE = + Pattern.compile("([^(]*\\([^)]*\\)[^,]*),\\s*"); + + String cpuFeaturesString = wb.getCPUFeatures(); + Matcher matcher = additionalCPUInfoRE.matcher(cpuFeaturesString); + if (matcher.find()) { + additionalCPUInfo = matcher.group(1); + } else { + additionalCPUInfo = ""; + } + String splittedFeatures[] = matcher.replaceAll("").split("(, )| "); + + features = Collections.unmodifiableList(Arrays. + asList(splittedFeatures)); + } + + /** + * Get additional information about CPU. + * For example, on X86 in will be family/model/stepping + * and number of cores. + * + * @return additional CPU info + */ + public static String getAdditionalCPUInfo() { + return additionalCPUInfo; + } + + /** + * Get all known features supported by CPU. + * + * @return unmodifiable list with names of all known features + * supported by CPU. + */ + public static List getFeatures() { + return features; + } + + /** + * Check if some feature is supported by CPU. + * + * @param feature Name of feature to be tested. + * @return true if tested feature is supported by CPU. + */ + public static boolean hasFeature(String feature) { + return features.contains(feature.toLowerCase()); + } +} diff -r 5b3afcfc9926 test/test/lib/sun/hotspot/parser/DiagnosticCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/test/lib/sun/hotspot/parser/DiagnosticCommand.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.parser; + +public class DiagnosticCommand { + + public enum DiagnosticArgumentType { + JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE + } + + private String name; + private String desc; + private DiagnosticArgumentType type; + private boolean mandatory; + private String defaultValue; + + public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, + boolean mandatory, String defaultValue) { + this.name = name; + this.desc = desc; + this.type = type; + this.mandatory = mandatory; + this.defaultValue = defaultValue; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public DiagnosticArgumentType getType() { + return type; + } + + public boolean isMandatory() { + return mandatory; + } + + public String getDefaultValue() { + return defaultValue; + } +} diff -r 5b3afcfc9926 test/vmTestbase/ExecDriver.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/ExecDriver.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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. + *

Usage: --java|--cmd|--launcher + + *

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}. + *

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. + *

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 value; + String name = Platform.sharedLibraryPathVariableName(); + if (Platform.isWindows()) { + value = dir.resolve("bin") + .resolve(variant()) + .toAbsolutePath() + .toString(); + value += File.pathSeparator; + value += dir.resolve("bin") + .toAbsolutePath() + .toString(); + } else { + value = dir.resolve("lib") + .resolve(variant()) + .toAbsolutePath() + .toString(); + } + + System.out.println(" with " + name + " = " + + pb.environment() + .merge(name, value, (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(); + } +} + diff -r 5b3afcfc9926 test/vmTestbase/PropertyResolvingWrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/PropertyResolvingWrapper.java Fri Sep 06 18:21:51 2019 +0300 @@ -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 ${}} 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 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(); + } +} diff -r 5b3afcfc9926 test/vmTestbase/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/README.md Fri Sep 06 18:21:51 2019 +0300 @@ -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. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle01/Juggle01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle01/Juggle01.java Fri Sep 06 18:21:51 2019 +0300 @@ -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. + */ + + +/* + * @test + * @key stress gc + * + * @summary converted from VM Testbase gc/ArrayJuggle/Juggle01. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, quick] + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm -Xloggc:gc.log gc.ArrayJuggle.Juggle01.Juggle01 -gp byteArr -ms low + */ + +package gc.ArrayJuggle.Juggle01; + +import nsk.share.test.*; +import nsk.share.gc.*; +import nsk.share.gc.gp.*; + +/** + * This test randomly replaces elements of an array with new + * objects using given garbage producer and memory strategy. + */ +public class Juggle01 extends ThreadedGCTest implements GarbageProducerAware, MemoryStrategyAware { + private GarbageProducer garbageProducer; + private MemoryStrategy memoryStrategy; + private Object[] array; + long objectSize; + + private class Juggler implements Runnable { + public void run() { + synchronized (this) { + int index = LocalRandom.nextInt(array.length); + array[index] = garbageProducer.create(objectSize); + } + } + } + + protected Runnable createRunnable(int i) { + return new Juggler(); + } + + public void run() { + log.debug("Garbage producer: " + garbageProducer); + log.debug("Memory strategy: " + memoryStrategy); + long memory = runParams.getTestMemory(); + int objectCount = memoryStrategy.getCount(memory); + objectSize = memoryStrategy.getSize(memory); + log.debug("Object count: " + objectCount); + log.debug("Object size: " + objectSize); + array = new Object[objectCount - 1]; + super.run(); + } + + public void setGarbageProducer(GarbageProducer garbageProducer) { + this.garbageProducer = garbageProducer; + } + + public void setMemoryStrategy(MemoryStrategy memoryStrategy) { + this.memoryStrategy = memoryStrategy; + } + + public static void main(String[] args) { + GC.runTest(new Juggle01(), args); + } +} diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle01/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle01/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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. +# +exclusiveAccess.dirs=. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle02/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle02/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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. +# +exclusiveAccess.dirs=. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle02/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle02/TestDescription.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,37 @@ +/* + * 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. + */ + + +/* + * @test + * @key stress gc + * + * @summary converted from VM Testbase gc/ArrayJuggle/Juggle02. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent] + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm -Xloggc:gc.log gc.ArrayJuggle.Juggle01.Juggle01 -gp byteArr -ms medium + */ + diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle03/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle03/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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. +# +exclusiveAccess.dirs=. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle03/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle03/TestDescription.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,37 @@ +/* + * 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. + */ + + +/* + * @test + * @key stress gc + * + * @summary converted from VM Testbase gc/ArrayJuggle/Juggle03. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent] + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm -Xloggc:gc.log gc.ArrayJuggle.Juggle01.Juggle01 -gp byteArr -ms high + */ + diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle04/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle04/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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. +# +exclusiveAccess.dirs=. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle04/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle04/TestDescription.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,37 @@ +/* + * 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. + */ + + +/* + * @test + * @key stress gc + * + * @summary converted from VM Testbase gc/ArrayJuggle/Juggle04. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent] + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm -Xloggc:gc.log gc.ArrayJuggle.Juggle01.Juggle01 -gp byteArr -ms low + */ + diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle05/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle05/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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. +# +exclusiveAccess.dirs=. diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle05/TestDescription.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle05/TestDescription.java Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,41 @@ +/* + * 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. + */ + + +/* + * @test + * @key stress gc + * + * @summary converted from VM Testbase gc/ArrayJuggle/Juggle05. + * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent] + * + * @library /vmTestbase + * /test/lib + * @run driver jdk.test.lib.FileInstaller . . + * @run main/othervm + * -Xloggc:gc.log + * gc.ArrayJuggle.Juggle01.Juggle01 + * -gp booleanArr + * -ms medium + */ + diff -r 5b3afcfc9926 test/vmTestbase/gc/ArrayJuggle/Juggle06/TEST.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/vmTestbase/gc/ArrayJuggle/Juggle06/TEST.properties Fri Sep 06 18:21:51 2019 +0300 @@ -0,0 +1,23 @@ +# +# 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