diff --git a/agent/src/os/linux/ps_proc.c b/agent/src/os/linux/ps_proc.c index 5ad3ff7f367a242bbc50c8fa5ca3c33d8c968b09..73b99c5002158c8fd064e0e2ce72372f33c4fe47 100644 --- a/agent/src/os/linux/ps_proc.c +++ b/agent/src/os/linux/ps_proc.c @@ -121,15 +121,13 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use #define ptrace_getregs(request, pid, addr, data) ptrace(request, pid, data, addr) #endif -#ifdef _LP64 -#ifdef PTRACE_GETREGS64 +#if defined(_LP64) && defined(PTRACE_GETREGS64) #define PTRACE_GETREGS_REQ PTRACE_GETREGS64 -#endif -#else -#if defined(PTRACE_GETREGS) || defined(PT_GETREGS) +#elif defined(PTRACE_GETREGS) #define PTRACE_GETREGS_REQ PTRACE_GETREGS +#elif defined(PT_GETREGS) +#define PTRACE_GETREGS_REQ PT_GETREGS #endif -#endif /* _LP64 */ #ifdef PTRACE_GETREGS_REQ if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { diff --git a/make/defs.make b/make/defs.make index 528d9405bf8520194a9ebc6d200835bfd3d0a878..48b91684ba7d33a8617ec56e56efdcab0fe937fd 100644 --- a/make/defs.make +++ b/make/defs.make @@ -101,15 +101,14 @@ ifndef HOTSPOT_RELEASE_VERSION endif ifdef HOTSPOT_BUILD_VERSION -# specified in command line (PRT build) +# specified in command line else - ifdef JPRT_BUILD_VERSION -# JPR build - HOTSPOT_BUILD_VERSION=$(JPRT_BUILD_VERSION) - else - ifdef COOKED_BUILD_NUMBER + ifdef COOKED_BUILD_NUMBER # JRE build - HOTSPOT_BUILD_VERSION= + HOTSPOT_BUILD_VERSION= + else + ifdef USER_RELEASE_SUFFIX + HOTSPOT_BUILD_VERSION=internal-$(USER_RELEASE_SUFFIX) else HOTSPOT_BUILD_VERSION=internal endif diff --git a/make/jprt.gmk b/make/jprt.gmk index b7f5292a1b504dc1bbb6bf565624f9d100f817d2..7495cc31456a48984a08da8b397603b50d82e9d2 100644 --- a/make/jprt.gmk +++ b/make/jprt.gmk @@ -25,9 +25,6 @@ # JPRT rule to build this workspace JPRT_ARCHIVE_BUNDLE=$(ABS_OUTPUTDIR)/$(JPRT_BUILD_FLAVOR)-bundle.zip -ifdef JPRT_BUILD_VERSION - MILESTONE=$(JPRT_BUILD_VERSION) -endif ifeq ($(OSNAME),windows) ZIPFLAGS=-q diff --git a/make/linux/makefiles/buildtree.make b/make/linux/makefiles/buildtree.make index 0089ac29c5cf1ce803a08f847c605ebc1f2ec8dd..a3edb07fc9484dd4269c9529833b5732a936a18a 100644 --- a/make/linux/makefiles/buildtree.make +++ b/make/linux/makefiles/buildtree.make @@ -37,7 +37,7 @@ # OS_FAMILY - operating system # VARIANT - core, compiler1, compiler2, or tiered # HOTSPOT_RELEASE_VERSION - .-b (11.0-b07) -# HOTSPOT_BUILD_VERSION - internal, PRTjob ID, JPRTjob ID +# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty # JRE_RELEASE_VERSION - .. (1.7.0) # # Builds the directory trees with makefiles plus some convenience files in diff --git a/make/linux/makefiles/gcc.make b/make/linux/makefiles/gcc.make index 2ba9228f6b98179b5f7cdaaf6f239fecba277073..1d7be454fd124eb69d74e7bd7f11ab5048e07fc3 100644 --- a/make/linux/makefiles/gcc.make +++ b/make/linux/makefiles/gcc.make @@ -42,11 +42,14 @@ CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) # check for precompiled headers support ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0" +# Allow the user to turn off precompiled headers from the command line. +ifneq ($(USE_PRECOMPILED_HEADER),0) USE_PRECOMPILED_HEADER=1 PRECOMPILED_HEADER_DIR=. PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch endif +endif #------------------------------------------------------------------------ @@ -150,6 +153,11 @@ ifneq ("${CC_VER_MAJOR}", "2") DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d) endif +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifneq ($(USE_PRECOMPILED_HEADER),1) +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + #------------------------------------------------------------------------ # Linker flags diff --git a/make/linux/makefiles/launcher.make b/make/linux/makefiles/launcher.make index b1ecf325054ad495b59bee7810ce1533d47eaac7..d9e34406bcb412807a5aef966275575d8791ee0c 100644 --- a/make/linux/makefiles/launcher.make +++ b/make/linux/makefiles/launcher.make @@ -24,19 +24,23 @@ # Rules to build gamma launcher, used by vm.make -# gamma[_g]: launcher +LAUNCHER_SCRIPT = hotspot LAUNCHER = gamma -LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX) -LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher -LAUNCHERFLAGS = $(ARCHFLAG) \ +LAUNCHERDIR := $(GAMMADIR)/src/os/posix/launcher +LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher +LAUNCHERFLAGS := $(ARCHFLAG) \ -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ + -I$(LAUNCHERDIR_SHARE) \ -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ -DARCH=\"$(LIBARCH)\" \ -DGAMMA \ -DLAUNCHER_TYPE=\"gamma\" \ - -DLINK_INTO_$(LINK_INTO) + -DLINK_INTO_$(LINK_INTO) \ + $(TARGET_DEFINES) ifeq ($(LINK_INTO),AOUT) LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) @@ -55,22 +59,35 @@ LINK_LAUNCHER = $(LINK.c) LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CC/PRE_HOOK) LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CC/POST_HOOK) -launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c - $(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) $(TARGET_DEFINES) - -launcher.c: - @echo Generating $@ - $(QUIETLY) { \ - echo '#define debug launcher_debug'; \ - echo '#include "java.c"'; \ - echo '#include "java_md.c"'; \ - } > $@ - -$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE) - $(QUIETLY) { \ - echo Linking launcher...; \ - $(LINK_LAUNCHER/PRE_HOOK) \ - $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER); \ - $(LINK_LAUNCHER/POST_HOOK) \ - [ -f $(LAUNCHER_G) ] || { ln -s $@ $(LAUNCHER_G); }; \ - } +LAUNCHER_OUT = launcher + +SUFFIXES += .d + +SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") +SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") + +OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) + +DEPFILES := $(patsubst %.o,%.d,$(OBJS)) +-include $(DEPFILES) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) + $(QUIETLY) echo Linking launcher... + $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) + $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER) + $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) + +$(LAUNCHER): $(LAUNCHER_SCRIPT) + +$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script + $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ + $(QUIETLY) chmod +x $@ + diff --git a/make/linux/makefiles/sparcWorks.make b/make/linux/makefiles/sparcWorks.make index f0a9901f70eb0006cf4f3b84ae17366d47d8cc77..d6fe9679b4bb473170e7becf1a6bc530a6e1bc16 100644 --- a/make/linux/makefiles/sparcWorks.make +++ b/make/linux/makefiles/sparcWorks.make @@ -79,6 +79,9 @@ ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d) endif +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER + #------------------------------------------------------------------------ # Linker flags diff --git a/make/linux/makefiles/vm.make b/make/linux/makefiles/vm.make index 0eb208da792562dd6cfc0881d7b28ed674136106..6ab3f738c2e3c3047490f6b60251b81feb467d73 100644 --- a/make/linux/makefiles/vm.make +++ b/make/linux/makefiles/vm.make @@ -173,7 +173,7 @@ endef Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) -Obj_Files = $(addsuffix .o,$(basename $(Src_Files))) +Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files)))) JVM_OBJ_FILES = $(Obj_Files) diff --git a/make/solaris/makefiles/buildtree.make b/make/solaris/makefiles/buildtree.make index 82eaf1f9a3465dac3ec79693ef016247a571108d..c0c7831e02f0d56f6e5cc9ad29370c877d91a6ee 100644 --- a/make/solaris/makefiles/buildtree.make +++ b/make/solaris/makefiles/buildtree.make @@ -37,7 +37,7 @@ # OS_FAMILY - operating system # VARIANT - core, compiler1, compiler2, or tiered # HOTSPOT_RELEASE_VERSION - .-b (11.0-b07) -# HOTSPOT_BUILD_VERSION - internal, PRTjob ID, JPRTjob ID +# HOTSPOT_BUILD_VERSION - internal, internal-$(USER_RELEASE_SUFFIX) or empty # JRE_RELEASE_VERSION - .. (1.7.0) # # Builds the directory trees with makefiles plus some convenience files in diff --git a/make/solaris/makefiles/gcc.make b/make/solaris/makefiles/gcc.make index 5a2072d96e1a999a6ef45ab9964f969c0f0777d8..b0cdfc9a23187bfe272995fb5514ce9aa813876a 100644 --- a/make/solaris/makefiles/gcc.make +++ b/make/solaris/makefiles/gcc.make @@ -47,11 +47,14 @@ $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2) # check for precompiled headers support ifneq "$(shell expr \( $(CC_VER_MAJOR) \> 3 \) \| \( \( $(CC_VER_MAJOR) = 3 \) \& \( $(CC_VER_MINOR) \>= 4 \) \))" "0" +# Allow the user to turn off precompiled headers from the command line. +ifneq ($(USE_PRECOMPILED_HEADER),0) USE_PRECOMPILED_HEADER=1 PRECOMPILED_HEADER_DIR=. PRECOMPILED_HEADER_SRC=$(GAMMADIR)/src/share/vm/precompiled.hpp PRECOMPILED_HEADER=$(PRECOMPILED_HEADER_DIR)/precompiled.hpp.gch endif +endif #------------------------------------------------------------------------ @@ -138,6 +141,11 @@ ifneq ("${CC_VER_MAJOR}", "2") DEPFLAGS = -MMD -MP -MF $(DEP_DIR)/$(@:%=%.d) endif +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +ifneq ($(USE_PRECOMPILED_HEADER),1) +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER +endif + #------------------------------------------------------------------------ # Linker flags diff --git a/make/solaris/makefiles/launcher.make b/make/solaris/makefiles/launcher.make index b5a2501774786a5a6e11c8ff9f682aa942c5eaeb..e0a2ee31640900c543ed293214d427882cf9a2b7 100644 --- a/make/solaris/makefiles/launcher.make +++ b/make/solaris/makefiles/launcher.make @@ -24,18 +24,22 @@ # Rules to build gamma launcher, used by vm.make -# gamma[_g]: launcher +LAUNCHER_SCRIPT = hotspot LAUNCHER = gamma -LAUNCHER_G = $(LAUNCHER)$(G_SUFFIX) -LAUNCHERDIR = $(GAMMADIR)/src/os/$(Platform_os_family)/launcher +LAUNCHERDIR = $(GAMMADIR)/src/os/posix/launcher +LAUNCHERDIR_SHARE := $(GAMMADIR)/src/share/tools/launcher LAUNCHERFLAGS = $(ARCHFLAG) \ -I$(LAUNCHERDIR) -I$(GAMMADIR)/src/share/vm/prims \ + -I$(LAUNCHERDIR_SHARE) \ -DFULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + -DJDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + -DJDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ -DARCH=\"$(LIBARCH)\" \ -DGAMMA \ -DLAUNCHER_TYPE=\"gamma\" \ - -DLINK_INTO_$(LINK_INTO) + -DLINK_INTO_$(LINK_INTO) \ + $(TARGET_DEFINES) ifeq ($(LINK_INTO),AOUT) LAUNCHER.o = launcher.o $(JVM_OBJ_FILES) @@ -68,24 +72,37 @@ ifeq ("${Platform_compiler}", "sparcWorks") #LAUNCHERFLAGS += -W0,-noglobal endif # Platform_compiler == sparcWorks -launcher.o: launcher.c $(LAUNCHERDIR)/java.c $(LAUNCHERDIR)/java_md.c - $(CC) -g -c -o $@ launcher.c $(LAUNCHERFLAGS) $(CPPFLAGS) ${TARGET_DEFINES} +LAUNCHER_OUT = launcher -launcher.c: - @echo Generating $@ - $(QUIETLY) { \ - echo '#define debug launcher_debug'; \ - echo '#include "java.c"'; \ - echo '#include "java_md.c"'; \ - } > $@ +SUFFIXES += .d -$(LAUNCHER): $(LAUNCHER.o) $(LIBJVM) $(LAUNCHER_MAPFILE) +SOURCES := $(shell find $(LAUNCHERDIR) -name "*.c") +SOURCES_SHARE := $(shell find $(LAUNCHERDIR_SHARE) -name "*.c") + +OBJS := $(patsubst $(LAUNCHERDIR)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES)) $(patsubst $(LAUNCHERDIR_SHARE)/%.c,$(LAUNCHER_OUT)/%.o,$(SOURCES_SHARE)) + +DEPFILES := $(patsubst %.o,%.d,$(OBJS)) +-include $(DEPFILES) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR_SHARE)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c + $(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); } + $(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CPPFLAGS) + +$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE) ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),) - @echo Linking launcher... + $(QUIETLY) echo Linking launcher... $(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK) - $(QUIETLY) \ - $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(LAUNCHER.o) $(LIBS_LAUNCHER) + $(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(OBJS) $(LIBS_LAUNCHER) $(QUIETLY) $(LINK_LAUNCHER/POST_HOOK) - [ -f $(LAUNCHER_G) ] || ln -s $@ $(LAUNCHER_G) endif # filter -sbfast -xsbfast +$(LAUNCHER): $(LAUNCHER_SCRIPT) + +$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script + $(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@ + $(QUIETLY) chmod +x $@ + diff --git a/make/solaris/makefiles/sparcWorks.make b/make/solaris/makefiles/sparcWorks.make index 4fed15513165cf5de9aa6d15468fd22a7951b12c..b3b0d514570192b125d2b2997d8a799c8fa33d19 100644 --- a/make/solaris/makefiles/sparcWorks.make +++ b/make/solaris/makefiles/sparcWorks.make @@ -150,6 +150,9 @@ ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) DEPFLAGS = -xMMD -xMF $(DEP_DIR)/$(@:%=%.d) endif +# -DDONT_USE_PRECOMPILED_HEADER will exclude all includes in precompiled.hpp. +CFLAGS += -DDONT_USE_PRECOMPILED_HEADER + ################################################ # Begin current (>=5.9) Forte compiler options # ################################################# diff --git a/make/solaris/makefiles/vm.make b/make/solaris/makefiles/vm.make index 28673be141c387fef07c95129ace395cf3bac7a4..508b1d878ceba0ead9ceac86554c113b7e240d4f 100644 --- a/make/solaris/makefiles/vm.make +++ b/make/solaris/makefiles/vm.make @@ -189,7 +189,7 @@ endef Src_Files := $(foreach e,$(Src_Dirs),$(call findsrc,$(e))) -Obj_Files = $(addsuffix .o,$(basename $(Src_Files))) +Obj_Files = $(sort $(addsuffix .o,$(basename $(Src_Files)))) JVM_OBJ_FILES = $(Obj_Files) $(DTRACE_OBJS) diff --git a/make/windows/makefiles/adlc.make b/make/windows/makefiles/adlc.make index 863ce07d3f79d3e057c4d0904027e699bd44a887..b3ba4110fb7f96f4da8d90fbb061b6fb64472e5c 100644 --- a/make/windows/makefiles/adlc.make +++ b/make/windows/makefiles/adlc.make @@ -46,7 +46,15 @@ ADLCFLAGS=-q -T -D_LP64 ADLCFLAGS=-q -T -U_LP64 !endif -CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE +CPP_FLAGS=$(CPP_FLAGS) \ + /D TARGET_OS_FAMILY_windows \ + /D TARGET_ARCH_$(Platform_arch) \ + /D TARGET_ARCH_MODEL_$(Platform_arch_model) \ + /D TARGET_OS_ARCH_windows_$(Platform_arch) \ + /D TARGET_OS_ARCH_MODEL_windows_$(Platform_arch_model) \ + /D TARGET_COMPILER_visCPP + +CPP_FLAGS=$(CPP_FLAGS) /D _CRT_SECURE_NO_WARNINGS /D _CRT_SECURE_NO_DEPRECATE CPP_INCLUDE_DIRS=\ /I "..\generated" \ diff --git a/make/windows/makefiles/debug.make b/make/windows/makefiles/debug.make index 73f5a397fa394a995f66dd5034a81758e658e688..fba050de5d281fb85be18c9b8feccc09ea94fa43 100644 --- a/make/windows/makefiles/debug.make +++ b/make/windows/makefiles/debug.make @@ -26,9 +26,15 @@ HS_INTERNAL_NAME=jvm HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) SAWINDBG=sawindbg.dll +LAUNCHER_NAME=hotspot.exe GENERATED=../generated -default:: _build_pch_file.obj $(AOUT) checkAndBuildSA +# Allow the user to turn off precompiled headers from the command line. +!if "$(USE_PRECOMPILED_HEADER)" != "0" +BUILD_PCH_FILE=_build_pch_file.obj +!endif + +default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA !include ../local.make !include compile.make @@ -57,3 +63,4 @@ $(AOUT): $(Res_Files) $(Obj_Files) !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/make/windows/makefiles/fastdebug.make b/make/windows/makefiles/fastdebug.make index a93c59cfc013f11e453033a7bc1d3ad6281efc3c..053ca8cabec65928dcbfe51c95c770b8eed7f1a5 100644 --- a/make/windows/makefiles/fastdebug.make +++ b/make/windows/makefiles/fastdebug.make @@ -26,9 +26,15 @@ HS_INTERNAL_NAME=jvm HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) SAWINDBG=sawindbg.dll +LAUNCHER_NAME=hotspot.exe GENERATED=../generated -default:: _build_pch_file.obj $(AOUT) checkAndBuildSA +# Allow the user to turn off precompiled headers from the command line. +!if "$(USE_PRECOMPILED_HEADER)" != "0" +BUILD_PCH_FILE=_build_pch_file.obj +!endif + +default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA !include ../local.make !include compile.make @@ -57,3 +63,4 @@ $(AOUT): $(Res_Files) $(Obj_Files) !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/make/windows/makefiles/launcher.make b/make/windows/makefiles/launcher.make new file mode 100644 index 0000000000000000000000000000000000000000..4afdb177a5297dfa69945d0b0dfd17f8209316f8 --- /dev/null +++ b/make/windows/makefiles/launcher.make @@ -0,0 +1,67 @@ +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +LAUNCHER_FLAGS=$(ARCHFLAG) \ + /D FULL_VERSION=\"$(HOTSPOT_RELEASE_VERSION)\" \ + /D JDK_MAJOR_VERSION=\"$(JDK_MAJOR_VERSION)\" \ + /D JDK_MINOR_VERSION=\"$(JDK_MINOR_VERSION)\" \ + /D GAMMA \ + /D LAUNCHER_TYPE=\"gamma\" \ + /D _CRT_SECURE_NO_WARNINGS \ + /D _CRT_SECURE_NO_DEPRECATE \ + /D LINK_INTO_LIBJVM \ + /I $(WorkSpace)\src\os\windows\launcher \ + /I $(WorkSpace)\src\share\tools\launcher + +CPP_FLAGS=$(CPP_FLAGS) $(LAUNCHER_FLAGS) + +LINK_FLAGS=/manifest $(HS_INTERNAL_NAME).lib kernel32.lib user32.lib /nologo /machine:$(MACHINE) /map /debug /subsystem:console + +!if "$(COMPILER_NAME)" == "VS2005" +# This VS2005 compiler has /GS as a default and requires bufferoverflowU.lib +# on the link command line, otherwise we get missing __security_check_cookie +# externals at link time. Even with /GS-, you need bufferoverflowU.lib. +BUFFEROVERFLOWLIB = bufferoverflowU.lib +LINK_FLAGS = $(LINK_FLAGS) $(BUFFEROVERFLOWLIB) +!endif + +LAUNCHERDIR = $(GAMMADIR)/src/os/windows/launcher +LAUNCHERDIR_SHARE = $(GAMMADIR)/src/share/tools/launcher + +OUTDIR = launcher + +{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) + $(CPP) $(CPP_FLAGS) /c /Fo$@ $< + +{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj: + -mkdir $(OUTDIR) + $(CPP) $(CPP_FLAGS) /c /Fo$@ $< + +$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h + +$(LAUNCHER_NAME): $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj + $(LINK) $(LINK_FLAGS) /out:$@ $** + + diff --git a/make/windows/makefiles/product.make b/make/windows/makefiles/product.make index 73c01536b12e268dcf6d2f63c25f0f549b791480..dab1e8485b48db8824ee79f1ad2f4937ca581e15 100644 --- a/make/windows/makefiles/product.make +++ b/make/windows/makefiles/product.make @@ -25,9 +25,15 @@ HS_INTERNAL_NAME=jvm HS_FNAME=$(HS_INTERNAL_NAME).dll AOUT=$(HS_FNAME) +LAUNCHER_NAME=hotspot.exe GENERATED=../generated -default:: _build_pch_file.obj $(AOUT) checkAndBuildSA +# Allow the user to turn off precompiled headers from the command line. +!if "$(USE_PRECOMPILED_HEADER)" != "0" +BUILD_PCH_FILE=_build_pch_file.obj +!endif + +default:: $(BUILD_PCH_FILE) $(AOUT) $(LAUNCHER_NAME) checkAndBuildSA !include ../local.make !include compile.make @@ -68,3 +74,4 @@ $(AOUT): $(Res_Files) $(Obj_Files) !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make +!include $(WorkSpace)/make/windows/makefiles/launcher.make diff --git a/make/windows/makefiles/vm.make b/make/windows/makefiles/vm.make index fb82e9c76137899e7e69586492badc7049a1ab40..a91a70fc4612ca4159e89cee56025f2c39aad569 100644 --- a/make/windows/makefiles/vm.make +++ b/make/windows/makefiles/vm.make @@ -128,7 +128,13 @@ CPP_INCLUDE_DIRS=\ /I "$(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm" \ /I "$(WorkSpace)\src\cpu\$(Platform_arch)\vm" +CPP_DONT_USE_PCH=/D DONT_USE_PRECOMPILED_HEADER + +!if "$(USE_PRECOMPILED_HEADER)" != "0" CPP_USE_PCH=/Fp"vm.pch" /Yu"precompiled.hpp" +!else +CPP_USE_PCH=$(CPP_DONT_USE_PCH) +!endif # Where to find the source code for the virtual machine VM_PATH=../generated @@ -164,31 +170,31 @@ VM_PATH={$(VM_PATH)} # Special case files not using precompiled header files. c1_RInfo_$(Platform_arch).obj: $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\cpu\$(Platform_arch)\vm\c1_RInfo_$(Platform_arch).cpp os_windows.obj: $(WorkSpace)\src\os\windows\vm\os_windows.cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\os_windows.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\os_windows.cpp os_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\os_windows_$(Platform_arch).cpp osThread_windows.obj: $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\osThread_windows.cpp conditionVar_windows.obj: $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os\windows\vm\conditionVar_windows.cpp getThread_windows_$(Platform_arch).obj: $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\os_cpu\windows_$(Platform_arch)\vm\getThread_windows_$(Platform_arch).cpp opcodes.obj: $(WorkSpace)\src\share\vm\opto\opcodes.cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\share\vm\opto\opcodes.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\share\vm\opto\opcodes.cpp bytecodeInterpreter.obj: $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp - $(CPP) $(CPP_FLAGS) /c $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c $(WorkSpace)\src\share\vm\interpreter\bytecodeInterpreter.cpp bytecodeInterpreterWithChecks.obj: ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp - $(CPP) $(CPP_FLAGS) /c ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp + $(CPP) $(CPP_FLAGS) $(CPP_DONT_USE_PCH) /c ..\generated\jvmtifiles\bytecodeInterpreterWithChecks.cpp # Default rules for the Virtual Machine {$(WorkSpace)\src\share\vm\c1}.cpp.obj:: diff --git a/make/windows/projectfiles/common/Makefile b/make/windows/projectfiles/common/Makefile index 3d9ae90110505e0746ac9021beb5417fbf08d77a..b1a9eceeb4e070d9b8ef251c3ffc2e3ad9eeb8a4 100644 --- a/make/windows/projectfiles/common/Makefile +++ b/make/windows/projectfiles/common/Makefile @@ -65,7 +65,11 @@ HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)" !else HOTSPOT_RELEASE_VERSION="$(HS_MAJOR_VER).$(HS_MINOR_VER)-b$(HS_BUILD_NUMBER)" !endif +!if "$(USER_RELEASE_SUFFIX)" != "" +HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal-$(USER_RELEASE_SUFFIX) +!else HOTSPOT_BUILD_VERSION$(HOTSPOT_BUILD_VERSION) = internal +!endif !if "$(HOTSPOT_BUILD_VERSION)" != "" HOTSPOT_RELEASE_VERSION="$(HOTSPOT_RELEASE_VERSION)-$(HOTSPOT_BUILD_VERSION)" !endif diff --git a/src/cpu/sparc/vm/depChecker_sparc.cpp b/src/cpu/sparc/vm/depChecker_sparc.cpp index f37545d97db7e38f7f19f029b3f42387c75f2dbf..abb0243a2f6154778567bc030a3b399acb35bd1c 100644 --- a/src/cpu/sparc/vm/depChecker_sparc.cpp +++ b/src/cpu/sparc/vm/depChecker_sparc.cpp @@ -25,6 +25,5 @@ #include "precompiled.hpp" #include "compiler/disassembler.hpp" #include "depChecker_sparc.hpp" -#include "runtime/hpi.hpp" // Nothing to do on Sparc diff --git a/src/cpu/x86/vm/assembler_x86.cpp b/src/cpu/x86/vm/assembler_x86.cpp index cb2ed5d08fabcda13da20143fb0278e5e349b610..8a2b2f9d4210545725050b1afc32380752d54a5d 100644 --- a/src/cpu/x86/vm/assembler_x86.cpp +++ b/src/cpu/x86/vm/assembler_x86.cpp @@ -5538,17 +5538,14 @@ void MacroAssembler::stop(const char* msg) { } void MacroAssembler::warn(const char* msg) { - push(r12); - movq(r12, rsp); + push(rsp); andq(rsp, -16); // align stack as required by push_CPU_state and call push_CPU_state(); // keeps alignment at 16 bytes lea(c_rarg0, ExternalAddress((address) msg)); call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0); pop_CPU_state(); - - movq(rsp, r12); - pop(r12); + pop(rsp); } #ifndef PRODUCT @@ -5860,6 +5857,10 @@ void MacroAssembler::call_VM_base(Register oop_result, // debugging support assert(number_of_arguments >= 0 , "cannot have negative number of arguments"); LP64_ONLY(assert(java_thread == r15_thread, "unexpected register")); +#ifdef ASSERT + LP64_ONLY(if (UseCompressedOops) verify_heapbase("call_VM_base");) +#endif // ASSERT + assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); assert(java_thread != last_java_sp, "cannot use the same register for java_thread & last_java_sp"); diff --git a/src/cpu/x86/vm/depChecker_x86.cpp b/src/cpu/x86/vm/depChecker_x86.cpp index fe3b8bcfe0ce9227ee47763e3e2992ccf50c38f8..f00d6453137975383d5182762efba5119b216028 100644 --- a/src/cpu/x86/vm/depChecker_x86.cpp +++ b/src/cpu/x86/vm/depChecker_x86.cpp @@ -25,6 +25,5 @@ #include "precompiled.hpp" #include "compiler/disassembler.hpp" #include "depChecker_x86.hpp" -#include "runtime/hpi.hpp" // Nothing to do on i486 diff --git a/src/cpu/x86/vm/interp_masm_x86_64.cpp b/src/cpu/x86/vm/interp_masm_x86_64.cpp index 75744bef645cd84e895ccaf6e826394b322d30bc..a156d24d66a8c2eed0ece59f2e1f8e2dbd93ee92 100644 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp @@ -449,10 +449,9 @@ void InterpreterMacroAssembler::jump_from_interpreted(Register method, Register // JVMTI events, such as single-stepping, are implemented partly by avoiding running // compiled code in threads for which the event is enabled. Check here for // interp_only_mode if these events CAN be enabled. - get_thread(temp); // interp_only is an int, on little endian it is sufficient to test the byte only - // Is a cmpl faster (ce - cmpb(Address(temp, JavaThread::interp_only_mode_offset()), 0); + // Is a cmpl faster? + cmpb(Address(r15_thread, JavaThread::interp_only_mode_offset()), 0); jcc(Assembler::zero, run_compiled_code); jmp(Address(method, methodOopDesc::interpreter_entry_offset())); bind(run_compiled_code); diff --git a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp index d48e980f6330299ecfbf20f971c412827d961888..2d7aa60cfcad06f9c0002e699eaae10a54c72336 100644 --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp @@ -1069,7 +1069,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { // runtime call by hand. // __ mov(c_rarg0, r15_thread); - __ mov(r12, rsp); // remember sp + __ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM) __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows __ andptr(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); @@ -1116,7 +1116,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) { __ jcc(Assembler::notEqual, no_reguard); __ pusha(); // XXX only save smashed registers - __ mov(r12, rsp); // remember sp + __ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM) __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows __ andptr(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); @@ -1907,7 +1907,7 @@ void TemplateInterpreterGenerator::trace_bytecode(Template* t) { assert(Interpreter::trace_code(t->tos_in()) != NULL, "entry must have been generated"); - __ mov(r12, rsp); // remember sp + __ mov(r12, rsp); // remember sp (can only use r12 if not using call_VM) __ andptr(rsp, -16); // align stack as required by ABI __ call(RuntimeAddress(Interpreter::trace_code(t->tos_in()))); __ mov(rsp, r12); // restore sp diff --git a/src/cpu/x86/vm/templateTable_x86_64.cpp b/src/cpu/x86/vm/templateTable_x86_64.cpp index 74d55160c4aa0155416915c6030f599e97ca182d..a396e88da8b7cc86ca6ab689dbf97dc06f07f529 100644 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp @@ -2762,7 +2762,7 @@ void TemplateTable::fast_accessfield(TosState state) { // access constant pool cache entry __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1); __ verify_oop(rax); - __ mov(r12, rax); // save object pointer before call_VM() clobbers it + __ push_ptr(rax); // save object pointer before call_VM() clobbers it __ mov(c_rarg1, rax); // c_rarg1: object pointer copied above // c_rarg2: cache entry pointer @@ -2770,8 +2770,7 @@ void TemplateTable::fast_accessfield(TosState state) { CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), c_rarg1, c_rarg2); - __ mov(rax, r12); // restore object pointer - __ reinit_heapbase(); + __ pop_ptr(rax); // restore object pointer __ bind(L1); } @@ -3365,10 +3364,7 @@ void TemplateTable::checkcast() { JVM_CONSTANT_Class); __ jcc(Assembler::equal, quicked); __ push(atos); // save receiver for result, and for GC - __ mov(r12, rcx); // save rcx XXX call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ movq(rcx, r12); // restore rcx XXX - __ reinit_heapbase(); __ pop_ptr(rdx); // restore receiver __ jmpb(resolved); @@ -3422,11 +3418,9 @@ void TemplateTable::instanceof() { __ jcc(Assembler::equal, quicked); __ push(atos); // save receiver for result, and for GC - __ mov(r12, rcx); // save rcx call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc)); - __ movq(rcx, r12); // restore rcx - __ reinit_heapbase(); __ pop_ptr(rdx); // restore receiver + __ verify_oop(rdx); __ load_klass(rdx, rdx); __ jmpb(resolved); diff --git a/src/cpu/zero/vm/depChecker_zero.cpp b/src/cpu/zero/vm/depChecker_zero.cpp index 163c10893ac7e13059e80a81129bc26d440048c6..fcc514141e54447f50ab11312efbbc3bf759ae88 100644 --- a/src/cpu/zero/vm/depChecker_zero.cpp +++ b/src/cpu/zero/vm/depChecker_zero.cpp @@ -26,6 +26,5 @@ #include "precompiled.hpp" #include "compiler/disassembler.hpp" #include "depChecker_zero.hpp" -#include "runtime/hpi.hpp" // This file is intentionally empty diff --git a/src/os/linux/vm/hpi_linux.cpp b/src/os/linux/vm/hpi_linux.cpp deleted file mode 100644 index 063e8a7a1541c8443610353cc9fac02aa2cf6b5e..0000000000000000000000000000000000000000 --- a/src/os/linux/vm/hpi_linux.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/hpi.hpp" -#include "runtime/os.hpp" - -# include -# include - -typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *); - -void hpi::initialize_get_interface(vm_calls_t *callbacks) { - char buf[JVM_MAXPATHLEN]; - void *hpi_handle; - GetInterfaceFunc& getintf = _get_interface; - jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *); - - if (HPILibPath && HPILibPath[0]) { - strncpy(buf, HPILibPath, JVM_MAXPATHLEN - 1); - buf[JVM_MAXPATHLEN - 1] = '\0'; - } else { - const char *thread_type = "native_threads"; - - os::jvm_path(buf, JVM_MAXPATHLEN); - -#ifdef PRODUCT - const char * hpi_lib = "/libhpi.so"; -#else - char * ptr = strrchr(buf, '/'); - assert(strstr(ptr, "/libjvm") == ptr, "invalid library name"); - const char * hpi_lib = strstr(ptr, "_g") ? "/libhpi_g.so" : "/libhpi.so"; -#endif - - *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ - char* p = strrchr(buf, '/'); - if (p != NULL) p[1] = '\0'; /* get rid of hotspot */ - strcat(buf, thread_type); - strcat(buf, hpi_lib); - } - - if (TraceHPI) tty->print_cr("Loading HPI %s ", buf); -#ifdef SPARC - // On 64-bit Ubuntu Sparc RTLD_NOW leads to unresolved deps in libpthread.so -# define OPEN_MODE RTLD_LAZY -#else - // We use RTLD_NOW because of bug 4032715 -# define OPEN_MODE RTLD_NOW -#endif - hpi_handle = dlopen(buf, OPEN_MODE); -#undef OPEN_MODE - - if (hpi_handle == NULL) { - if (TraceHPI) tty->print_cr("HPI dlopen failed: %s", dlerror()); - return; - } - DLL_Initialize = CAST_TO_FN_PTR(jint (JNICALL *)(GetInterfaceFunc *, void *), - dlsym(hpi_handle, "DLL_Initialize")); - if (TraceHPI && DLL_Initialize == NULL) tty->print_cr("HPI dlsym of DLL_Initialize failed: %s", dlerror()); - if (DLL_Initialize == NULL || - (*DLL_Initialize)(&getintf, callbacks) < 0) { - if (TraceHPI) tty->print_cr("HPI DLL_Initialize failed"); - return; - } - if (TraceHPI) tty->print_cr("HPI loaded successfully"); -} diff --git a/src/os/linux/vm/hpi_linux.hpp b/src/os/linux/vm/hpi_linux.hpp deleted file mode 100644 index 5e698264f04b49197c4ca3dafb0fc66a9241c2fc..0000000000000000000000000000000000000000 --- a/src/os/linux/vm/hpi_linux.hpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 OS_LINUX_VM_HPI_LINUX_HPP -#define OS_LINUX_VM_HPI_LINUX_HPP - -// -// Because the interruptible IO has been dropped for HotSpot/Linux, -// the following HPI interface is very different from HotSparc. -// - -#include -#include -#include -#include -#include - -// HPI_FileInterface - -inline int hpi::close(int fd) { - return ::close(fd); -} - -inline size_t hpi::read(int fd, void *buf, unsigned int nBytes) { - size_t res; - RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res); - return res; -} - -inline size_t hpi::write(int fd, const void *buf, unsigned int nBytes) { - size_t res; - RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); - return res; -} - - -// HPI_SocketInterface - -inline int hpi::socket_close(int fd) { - return ::close(fd); -} - -inline int hpi::socket(int domain, int type, int protocol) { - return ::socket(domain, type, protocol); -} - -inline int hpi::recv(int fd, char *buf, int nBytes, int flags) { - RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags)); -} - -inline int hpi::send(int fd, char *buf, int nBytes, int flags) { - RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags)); -} - -inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) { - return send(fd, buf, nBytes, flags); -} - -inline int hpi::timeout(int fd, long timeout) { - julong prevtime,newtime; - struct timeval t; - - gettimeofday(&t, NULL); - prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; - - for(;;) { - struct pollfd pfd; - - pfd.fd = fd; - pfd.events = POLLIN | POLLERR; - - int res = ::poll(&pfd, 1, timeout); - - if (res == OS_ERR && errno == EINTR) { - - // On Linux any value < 0 means "forever" - - if(timeout >= 0) { - gettimeofday(&t, NULL); - newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; - timeout -= newtime - prevtime; - if(timeout <= 0) - return OS_OK; - prevtime = newtime; - } - } else - return res; - } -} - -inline int hpi::listen(int fd, int count) { - return ::listen(fd, count); -} - -inline int hpi::connect(int fd, struct sockaddr *him, int len) { - RESTARTABLE_RETURN_INT(::connect(fd, him, len)); -} - -inline int hpi::accept(int fd, struct sockaddr *him, int *len) { - // This cast is from int to unsigned int on linux. Since we - // only pass the parameter "len" around the vm and don't try to - // fetch it's value, this cast is safe for now. The java.net group - // may need and want to change this interface someday if socklen_t goes - // to 64 bits on some platform that we support. - // Linux doc says this can't return EINTR, unlike accept() on Solaris - - return ::accept(fd, him, (socklen_t *)len); -} - -inline int hpi::recvfrom(int fd, char *buf, int nBytes, int flags, - sockaddr *from, int *fromlen) { - RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen)); -} - -inline int hpi::sendto(int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen) { - RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen)); -} - -inline int hpi::socket_available(int fd, jint *pbytes) { - // Linux doc says EINTR not returned, unlike Solaris - int ret = ::ioctl(fd, FIONREAD, pbytes); - - //%% note ioctl can return 0 when successful, JVM_SocketAvailable - // is expected to return 0 on failure and 1 on success to the jdk. - return (ret < 0) ? 0 : 1; -} - - -// following methods have been updated to avoid problems in -// hpi's sockets calls based on sys_api_td.c (JDK1.3) - -/* -HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown, - int, "%d", - (int fd, int howto), - ("fd = %d, howto = %d", fd, howto), - (fd, howto)); - */ -inline int hpi::socket_shutdown(int fd, int howto){ - return ::shutdown(fd, howto); -} - -/* -HPIDECL(bind, "bind", _socket, Bind, - int, "%d", - (int fd, struct sockaddr *him, int len), - ("fd = %d, him = %p, len = %d", - fd, him, len), - (fd, him, len)); -*/ -inline int hpi::bind(int fd, struct sockaddr *him, int len){ - return ::bind(fd, him, len); -} - -/* -HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName, - int, "%d", - (int fd, struct sockaddr *him, int *len), - ("fd = %d, him = %p, len = %p", - fd, him, len), - (fd, him, len)); - */ -inline int hpi::get_sock_name(int fd, struct sockaddr *him, int *len){ - return ::getsockname(fd, him, (socklen_t *)len); -} - -/* -HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d", - (char *hostname, int namelen), - ("hostname = %p, namelen = %d", - hostname, namelen), - (hostname, namelen)); - */ -inline int hpi::get_host_name(char* name, int namelen){ - return ::gethostname(name, namelen); -} - -/* -HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d", - (int fd, int level, int optname, char *optval, int* optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - */ -inline int hpi::get_sock_opt(int fd, int level, int optname, - char *optval, int* optlen){ - return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen); -} - -/* -HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d", - (int fd, int level, int optname, const char *optval, int optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - */ -inline int hpi::set_sock_opt(int fd, int level, int optname, - const char *optval, int optlen){ - return ::setsockopt(fd, level, optname, optval, optlen); -} - - -// Reconciliation History -// hpi_solaris.hpp 1.9 99/08/30 16:31:23 -// End - -#endif // OS_LINUX_VM_HPI_LINUX_HPP diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp index f47bd62c7217700989f8a19c6837ee6de7ef682e..b0e0f247539055edc56eec1b5938d22c77c7149b 100644 --- a/src/os/linux/vm/os_linux.cpp +++ b/src/os/linux/vm/os_linux.cpp @@ -44,7 +44,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -1565,6 +1564,24 @@ void os::die() { // unused on linux for now. void os::set_error_file(const char *logfile) {} + +// This method is a copy of JDK's sysGetLastErrorString +// from src/solaris/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + + if (errno == 0) return 0; + + const char *s = ::strerror(errno); + size_t n = ::strlen(s); + if (n >= len) { + n = len - 1; + } + ::strncpy(buf, s, n); + buf[n] = '\0'; + return n; +} + intx os::current_thread_id() { return (intx)pthread_self(); } int os::current_process_id() { @@ -1929,19 +1946,19 @@ void* os::dll_lookup(void* handle, const char* name) { } -bool _print_ascii_file(const char* filename, outputStream* st) { - int fd = open(filename, O_RDONLY); +static bool _print_ascii_file(const char* filename, outputStream* st) { + int fd = ::open(filename, O_RDONLY); if (fd == -1) { return false; } char buf[32]; int bytes; - while ((bytes = read(fd, buf, sizeof(buf))) > 0) { + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { st->print_raw(buf, bytes); } - close(fd); + ::close(fd); return true; } @@ -2219,8 +2236,6 @@ void os::jvm_path(char *buf, jint buflen) { // Use current module name "libjvm[_g].so" instead of // "libjvm"debug_only("_g")".so" since for fastdebug version // we should have "libjvm.so" but debug_only("_g") adds "_g"! - // It is used when we are choosing the HPI library's name - // "libhpi[_g].so" in hpi::initialize_get_interface(). len = strlen(buf); snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); } else { @@ -2404,18 +2419,18 @@ void linux_wrap_code(char* base, size_t size) { os::get_temp_directory(), os::current_process_id(), num); unlink(buf); - int fd = open(buf, O_CREAT | O_RDWR, S_IRWXU); + int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU); if (fd != -1) { - off_t rv = lseek(fd, size-2, SEEK_SET); + off_t rv = ::lseek(fd, size-2, SEEK_SET); if (rv != (off_t)-1) { - if (write(fd, "", 1) == 1) { + if (::write(fd, "", 1) == 1) { mmap(base, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0); } } - close(fd); + ::close(fd); unlink(buf); } } @@ -4047,13 +4062,6 @@ jint os::init_2(void) // Initialize lock used to serialize thread creation (see os::create_thread) Linux::set_createThread_lock(new Mutex(Mutex::leaf, "createThread_lock", false)); - // Initialize HPI. - jint hpi_result = hpi::initialize(); - if (hpi_result != JNI_OK) { - tty->print_cr("There was an error trying to initialize the HPI library."); - return hpi_result; - } - // at-exit methods are called in the reverse order of their registration. // atexit functions are called on return from main or as a result of a // call to exit(3C). There can be only 32 of these functions registered @@ -4251,7 +4259,7 @@ int os::stat(const char *path, struct stat *sbuf) { errno = ENAMETOOLONG; return -1; } - hpi::native_path(strcpy(pathbuf, path)); + os::native_path(strcpy(pathbuf, path)); return ::stat(pathbuf, sbuf); } @@ -4283,6 +4291,85 @@ bool os::dir_is_empty(const char* path) { return result; } +// This code originates from JDK's sysOpen and open64_w +// from src/solaris/hpi/src/system_md.c + +#ifndef O_DELETE +#define O_DELETE 0x10000 +#endif + +// Open a file. Unlink the file immediately after open returns +// if the specified oflag has the O_DELETE flag set. +// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c + +int os::open(const char *path, int oflag, int mode) { + + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + int fd; + int o_delete = (oflag & O_DELETE); + oflag = oflag & ~O_DELETE; + + fd = ::open64(path, oflag, mode); + if (fd == -1) return -1; + + //If the open succeeded, the file might still be a directory + { + struct stat64 buf64; + int ret = ::fstat64(fd, &buf64); + int st_mode = buf64.st_mode; + + if (ret != -1) { + if ((st_mode & S_IFMT) == S_IFDIR) { + errno = EISDIR; + ::close(fd); + return -1; + } + } else { + ::close(fd); + return -1; + } + } + + /* + * All file descriptors that are opened in the JVM and not + * specifically destined for a subprocess should have the + * close-on-exec flag set. If we don't set it, then careless 3rd + * party native code might fork and exec without closing all + * appropriate file descriptors (e.g. as we do in closeDescriptors in + * UNIXProcess.c), and this in turn might: + * + * - cause end-of-file to fail to be detected on some file + * descriptors, resulting in mysterious hangs, or + * + * - might cause an fopen in the subprocess to fail on a system + * suffering from bug 1085341. + * + * (Yes, the default setting of the close-on-exec flag is a Unix + * design flaw) + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 4843136: (process) pipe file descriptor from Runtime.exec not being closed + * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 + */ +#ifdef FD_CLOEXEC + { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + if (o_delete != 0) { + ::unlink(path); + } + return fd; +} + + // create binary file, rewriting existing file if required int os::create_binary_file(const char* path, bool rewrite_existing) { int oflags = O_WRONLY | O_CREAT; @@ -4302,6 +4389,40 @@ jlong os::seek_to_file_offset(int fd, jlong offset) { return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET); } +// This code originates from JDK's sysAvailable +// from src/solaris/hpi/src/native_threads/src/sys_api_td.c + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + int mode; + struct stat64 buf64; + + if (::fstat64(fd, &buf64) >= 0) { + mode = buf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { + /* + * XXX: is the following call interruptible? If so, this might + * need to go through the INTERRUPT_IO() wrapper as for other + * blocking, interruptible calls in this file. + */ + int n; + if (::ioctl(fd, FIONREAD, &n) >= 0) { + *bytes = n; + return 1; + } + } + } + if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) { + return 0; + } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) { + return 0; + } else if (::lseek64(fd, cur, SEEK_SET) == -1) { + return 0; + } + *bytes = end - cur; + return 1; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -4528,7 +4649,7 @@ void os::pause() { int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd != -1) { struct stat buf; - close(fd); + ::close(fd); while (::stat(filename, &buf) == 0) { (void)::poll(NULL, 0, 100); } diff --git a/src/os/linux/vm/os_linux.inline.hpp b/src/os/linux/vm/os_linux.inline.hpp index 002b23ea9d466afa61cfd6b2e37f165f4f9dc15b..6e52d108fb82ea5296fb18d96d67f15a58d441b5 100644 --- a/src/os/linux/vm/os_linux.inline.hpp +++ b/src/os/linux/vm/os_linux.inline.hpp @@ -40,6 +40,14 @@ # include "orderAccess_linux_zero.inline.hpp" #endif +// System includes + +#include +#include +#include +#include +#include + inline void* os::thread_local_storage_at(int index) { return pthread_getspecific((pthread_key_t)index); } @@ -93,6 +101,12 @@ inline void os::split_reserved_memory(char *base, size_t size, inline void os::bang_stack_shadow_pages() { } +inline void os::dll_unload(void *lib) { + ::dlclose(lib); +} + +inline const int os::default_file_open_flags() { return 0;} + inline DIR* os::opendir(const char* dirname) { assert(dirname != NULL, "just checking"); @@ -104,6 +118,22 @@ inline int os::readdir_buf_size(const char *path) return NAME_MAX + sizeof(dirent) + 1; } +inline jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::lseek64(fd, offset, whence); +} + +inline int os::fsync(int fd) { + return ::fsync(fd); +} + +inline char* os::native_path(char *path) { + return path; +} + +inline int os::ftruncate(int fd, jlong length) { + return ::ftruncate64(fd, length); +} + inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf) { dirent* p; @@ -121,9 +151,8 @@ inline struct dirent* os::readdir(DIR* dirp, dirent *dbuf) return p; } -inline int os::closedir(DIR *dirp) -{ - assert(dirp != NULL, "just checking"); +inline int os::closedir(DIR *dirp) { + assert(dirp != NULL, "argument is NULL"); return ::closedir(dirp); } @@ -142,4 +171,139 @@ inline int os::closedir(DIR *dirp) inline bool os::numa_has_static_binding() { return true; } inline bool os::numa_has_group_homing() { return false; } +inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE( (size_t) ::read(fd, buf, (size_t) nBytes), res); + return res; +} + +inline size_t os::write(int fd, const void *buf, unsigned int nBytes) { + size_t res; + RESTARTABLE((size_t) ::write(fd, buf, (size_t) nBytes), res); + return res; +} + +inline int os::close(int fd) { + return ::close(fd); +} + +inline int os::socket_close(int fd) { + return ::close(fd); +} + +inline int os::socket(int domain, int type, int protocol) { + return ::socket(domain, type, protocol); +} + +inline int os::recv(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::recv(fd, buf, nBytes, (unsigned int) flags)); +} + +inline int os::send(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, (unsigned int) flags)); +} + +inline int os::raw_send(int fd, char *buf, int nBytes, int flags) { + return os::send(fd, buf, nBytes, flags); +} + +inline int os::timeout(int fd, long timeout) { + julong prevtime,newtime; + struct timeval t; + + gettimeofday(&t, NULL); + prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + struct pollfd pfd; + + pfd.fd = fd; + pfd.events = POLLIN | POLLERR; + + int res = ::poll(&pfd, 1, timeout); + + if (res == OS_ERR && errno == EINTR) { + + // On Linux any value < 0 means "forever" + + if(timeout >= 0) { + gettimeofday(&t, NULL); + newtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else + return res; + } +} + +inline int os::listen(int fd, int count) { + return ::listen(fd, count); +} + +inline int os::connect(int fd, struct sockaddr *him, int len) { + RESTARTABLE_RETURN_INT(::connect(fd, him, len)); +} + +inline int os::accept(int fd, struct sockaddr *him, int *len) { + // This cast is from int to unsigned int on linux. Since we + // only pass the parameter "len" around the vm and don't try to + // fetch it's value, this cast is safe for now. The java.net group + // may need and want to change this interface someday if socklen_t goes + // to 64 bits on some platform that we support. + // Linux doc says this can't return EINTR, unlike accept() on Solaris + + return ::accept(fd, him, (socklen_t *)len); +} + +inline int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + RESTARTABLE_RETURN_INT(::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen)); +} + +inline int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + RESTARTABLE_RETURN_INT(::sendto(fd, buf, len, (unsigned int) flags, to, tolen)); +} + +inline int os::socket_available(int fd, jint *pbytes) { + // Linux doc says EINTR not returned, unlike Solaris + int ret = ::ioctl(fd, FIONREAD, pbytes); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + return (ret < 0) ? 0 : 1; +} + + +inline int os::socket_shutdown(int fd, int howto){ + return ::shutdown(fd, howto); +} + +inline int os::bind(int fd, struct sockaddr *him, int len){ + return ::bind(fd, him, len); +} + +inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){ + return ::getsockname(fd, him, (socklen_t *)len); +} + +inline int os::get_host_name(char* name, int namelen){ + return ::gethostname(name, namelen); +} + +inline struct hostent* os::get_host_by_name(char* name) { + return ::gethostbyname(name); +} +inline int os::get_sock_opt(int fd, int level, int optname, + char *optval, int* optlen){ + return ::getsockopt(fd, level, optname, optval, (socklen_t *)optlen); +} + +inline int os::set_sock_opt(int fd, int level, int optname, + const char *optval, int optlen){ + return ::setsockopt(fd, level, optname, optval, optlen); +} #endif // OS_LINUX_VM_OS_LINUX_INLINE_HPP diff --git a/src/os/linux/launcher/java_md.c b/src/os/posix/launcher/java_md.c similarity index 88% rename from src/os/linux/launcher/java_md.c rename to src/os/posix/launcher/java_md.c index 7af7e52a56ab41fe7fea6c4b1c396abbe436d13c..dd45278f2b5e93e65f50d7e0bd2c800e9eb5eef2 100644 --- a/src/os/linux/launcher/java_md.c +++ b/src/os/posix/launcher/java_md.c @@ -22,10 +22,6 @@ * */ -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ #include "java.h" #include @@ -45,64 +41,42 @@ #include "version_comp.h" #endif +#ifdef __linux__ +#include +#else +#include +#endif + #define JVM_DLL "libjvm.so" #define JAVA_DLL "libjava.so" #ifndef GAMMA /* launcher.make defines ARCH */ - /* * If a processor / os combination has the ability to run binaries of * two data models and cohabitation of jre/jdk bits with both data * models is supported, then DUAL_MODE is defined. When DUAL_MODE is * defined, the architecture names for the narrow and wide version of - * the architecture are defined in BIG_ARCH and SMALL_ARCH. Currently + * the architecture are defined in LIBARCH64NAME and LIBARCH32NAME. Currently * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux * i586/amd64 could be defined as DUAL_MODE but that is not the * current policy. */ -#ifdef _LP64 - -# ifdef ia64 -# define ARCH "ia64" -# elif defined(amd64) -# define ARCH "amd64" -# elif defined(__sparc) -# define ARCH "sparcv9" -# else -# define ARCH "unknown" /* unknown 64-bit architecture */ -# endif - -#else /* 32-bit data model */ - -# ifdef i586 -# define ARCH "i386" -# elif defined(__sparc) -# define ARCH "sparc" -# elif defined(arm) -# define ARCH "arm" -# elif defined(PPC) -# define ARCH "ppc" -# endif - -#endif /* _LP64 */ +#ifndef LIBARCHNAME +# error "The macro LIBARCHNAME was not defined on the compile line" +#endif #ifdef __sun # define DUAL_MODE -# ifdef __sparc -# define BIG_ARCH "sparcv9" -# define SMALL_ARCH "sparc" -# else -# define BIG_ARCH "amd64" -# define SMALL_ARCH "i386" +# ifndef LIBARCH32NAME +# error "The macro LIBARCH32NAME was not defined on the compile line" +# endif +# ifndef LIBARCH64NAME +# error "The macro LIBARCH64NAME was not defined on the compile line" # endif # include # include # include -#else -# ifndef ARCH -# include -# endif #endif #endif /* ifndef GAMMA */ @@ -111,7 +85,6 @@ extern char **environ; #ifndef GAMMA - /* * A collection of useful strings. One should think of these as #define * entries, but actual strings can be more efficient (with many compilers). @@ -124,7 +97,7 @@ static const char *system_dir = "/usr/jdk"; static const char *user_dir = "/jdk"; #endif -#endif /* ifndef GAMMA */ +#endif /* ifndef GAMMA */ /* * Flowchart of launcher execs and options processing on unix @@ -196,23 +169,13 @@ static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, char *jvmpath, jint jvmpathsize, char * arch); static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative); +#ifndef GAMMA const char * GetArch() { - static char *arch = NULL; - static char buf[12]; - if (arch) { - return arch; - } - -#ifdef ARCH - strcpy(buf, ARCH); -#else - sysinfo(SI_ARCHITECTURE, buf, sizeof(buf)); -#endif - arch = buf; - return arch; + return LIBARCHNAME; } +#endif /* ifndef GAMMA */ void CreateExecutionEnvironment(int *_argcp, @@ -287,7 +250,7 @@ CreateExecutionEnvironment(int *_argcp, { /* open new scope to declare local variables */ int i; - newargv = (char **)MemAlloc((argc+1) * sizeof(*newargv)); + newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv)); newargv[newargc++] = argv[0]; /* scan for data model arguments and remove from argument list; @@ -358,7 +321,7 @@ CreateExecutionEnvironment(int *_argcp, #ifdef DUAL_MODE if (running != wanted) { /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE)) { + if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) { goto EndDataModelSpeculate; } @@ -366,14 +329,14 @@ CreateExecutionEnvironment(int *_argcp, * Read in jvm.cfg for target data model and process vm * selection options. */ - if (ReadKnownVMs(jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE) < 1) { + if (ReadKnownVMs(jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE) < 1) { goto EndDataModelSpeculate; } jvmpath[0] = '\0'; jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE); /* exec child can do error checking on the existence of the path */ jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, - ((wanted==64)?BIG_ARCH:SMALL_ARCH)); + ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)); } EndDataModelSpeculate: /* give up and let other code report error message */ @@ -388,8 +351,8 @@ CreateExecutionEnvironment(int *_argcp, * We will set the LD_LIBRARY_PATH as follows: * * o $JVMPATH (directory portion only) - * o $JRE/lib/$ARCH - * o $JRE/../lib/$ARCH + * o $JRE/lib/$LIBARCHNAME + * o $JRE/../lib/$LIBARCHNAME * * followed by the user's previous effective LD_LIBRARY_PATH, if * any. @@ -483,8 +446,8 @@ CreateExecutionEnvironment(int *_argcp, /* runpath contains current effective LD_LIBRARY_PATH setting */ - jvmpath = strdup(jvmpath); - new_runpath = MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + + jvmpath = JLI_StringDup(jvmpath); + new_runpath = JLI_MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + 2*strlen(jrepath) + 2*strlen(arch) + strlen(jvmpath) + 52); newpath = new_runpath + strlen("LD_LIBRARY_PATH="); @@ -500,7 +463,7 @@ CreateExecutionEnvironment(int *_argcp, *lastslash = '\0'; - /* jvmpath, ((running != wanted)?((wanted==64)?"/"BIG_ARCH:"/.."):""), */ + /* jvmpath, ((running != wanted)?((wanted==64)?"/"LIBARCH64NAME:"/.."):""), */ sprintf(new_runpath, "LD_LIBRARY_PATH=" "%s:" @@ -508,8 +471,8 @@ CreateExecutionEnvironment(int *_argcp, "%s/../lib/%s", jvmpath, #ifdef DUAL_MODE - jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), - jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH) + jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME), + jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME) #else jrepath, arch, jrepath, arch @@ -576,7 +539,7 @@ CreateExecutionEnvironment(int *_argcp, * executable must be updated accordingly; the executable name * and directory the executable resides in are separate. In the * case of 32 => 64, the new bits are assumed to reside in, e.g. - * "olddir/BIGARCH/execname"; in the case of 64 => 32, + * "olddir/LIBARCH64NAME/execname"; in the case of 64 => 32, * the bits are assumed to be in "olddir/../execname". For example, * * olddir/sparcv9/execname @@ -586,19 +549,21 @@ CreateExecutionEnvironment(int *_argcp, */ if (running != wanted) { - char *oldexec = strcpy(MemAlloc(strlen(execname) + 1), execname); + char *oldexec = strcpy(JLI_MemAlloc(strlen(execname) + 1), execname); char *olddir = oldexec; char *oldbase = strrchr(oldexec, '/'); - newexec = MemAlloc(strlen(execname) + 20); + newexec = JLI_MemAlloc(strlen(execname) + 20); *oldbase++ = 0; sprintf(newexec, "%s/%s/%s", olddir, - ((wanted==64) ? BIG_ARCH : ".."), oldbase); + ((wanted==64) ? LIBARCH64NAME : ".."), oldbase); argv[0] = newexec; } #endif + (void)fflush(stdout); + (void)fflush(stderr); execve(newexec, argv, newenvp); perror("execve()"); @@ -630,12 +595,14 @@ CreateExecutionEnvironment(int *_argcp, #else /* ifndef GAMMA */ - /* gamma launcher is simpler in that it doesn't handle VM flavors, data */ - /* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly */ - /* all we need to do here is to return correct path names. See also */ - /* GetJVMPath() and GetApplicationHome(). */ + /* + * gamma launcher is simpler in that it doesn't handle VM flavors, data + * model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly + * all we need to do here is to return correct path names. See also + * GetJVMPath() and GetApplicationHome(). + */ - { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ + { char *arch = (char *) ARCH; /* like sparc or sparcv9 */ char *p; if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { @@ -669,9 +636,11 @@ GetJVMPath(const char *jrepath, const char *jvmtype, sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); } #else - /* For gamma launcher, JVM is either built-in or in the same directory. */ - /* Either way we return "/libjvm.so" where is the */ - /* directory where gamma launcher is located. */ + /* + * For gamma launcher, JVM is either built-in or in the same directory. + * Either way we return "/libjvm.so" where is the + * directory where gamma launcher is located. + */ char *p; @@ -684,7 +653,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype, /* this case shouldn't happen */ snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); } -#endif +#endif /* ifndef GAMMA */ if (_launcher_debug) printf("Does `%s' exist ... ", jvmpath); @@ -742,7 +711,7 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; return JNI_TRUE; #else - Dl_info dlinfo; + Dl_info dlinfo; void *libjvm; if (_launcher_debug) { @@ -813,24 +782,7 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) error: fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror()); return JNI_FALSE; -#endif /* GAMMA */ -} - -/* - * Get the path to the file that has the usage message for -X options. - */ -void -GetXUsagePath(char *buf, jint bufsize) -{ - static const char Xusage_txt[] = "/Xusage.txt"; - Dl_info dlinfo; - - /* we use RTLD_NOW because of problems with ld.so.1 and green threads */ - dladdr(dlsym(dlopen(JVM_DLL, RTLD_NOW), "JNI_CreateJavaVM"), &dlinfo); - strncpy(buf, (char *)dlinfo.dli_fname, bufsize - sizeof(Xusage_txt)); - - buf[bufsize-1] = '\0'; - strcpy(strrchr(buf, '/'), Xusage_txt); +#endif /* ifndef GAMMA */ } /* @@ -860,13 +812,16 @@ GetApplicationHome(char *buf, jint bufsize) #ifdef GAMMA { - /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */ - char* java_home_var = getenv("JAVA_HOME"); - if (java_home_var == NULL) { - printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); - return JNI_FALSE; - } - snprintf(buf, bufsize, "%s", java_home_var); + /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */ + char* java_home_var = getenv("ALT_JAVA_HOME"); + if (java_home_var == NULL) { + java_home_var = getenv("JAVA_HOME"); + } + if (java_home_var == NULL) { + printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); + return JNI_FALSE; + } + snprintf(buf, bufsize, "%s", java_home_var); } #else if (strrchr(buf, '/') == 0) { @@ -885,7 +840,7 @@ GetApplicationHome(char *buf, jint bufsize) return JNI_FALSE; } *(strrchr(buf, '/')) = '\0'; /* bin */ -#endif /* GAMMA */ +#endif /* ifndef GAMMA */ return JNI_TRUE; } @@ -915,7 +870,7 @@ Resolve(char *indir, char *cmd) if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0; sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd); if (!ProgramExists(name)) return 0; - real = MemAlloc(PATH_MAX + 2); + real = JLI_MemAlloc(PATH_MAX + 2); if (!realpath(name, real)) strcpy(real, name); return real; @@ -948,7 +903,7 @@ FindExecName(char *program) /* from search path? */ path = getenv("PATH"); if (!path || !*path) path = "."; - tmp_path = MemAlloc(strlen(path) + 2); + tmp_path = JLI_MemAlloc(strlen(path) + 2); strcpy(tmp_path, path); for (f=tmp_path; *f && result==0; ) { @@ -967,7 +922,7 @@ FindExecName(char *program) if (result != 0) break; } - free(tmp_path); + JLI_MemFree(tmp_path); return result; } @@ -1000,11 +955,11 @@ SetExecname(char **argv) { Dl_info dlinfo; if (dladdr((void*)&SetExecname, &dlinfo)) { - char *resolved = (char*)MemAlloc(PATH_MAX+1); + char *resolved = (char*)JLI_MemAlloc(PATH_MAX+1); if (resolved != NULL) { exec_path = realpath(dlinfo.dli_fname, resolved); if (exec_path == NULL) { - free(resolved); + JLI_MemFree(resolved); } } } @@ -1016,7 +971,7 @@ SetExecname(char **argv) int len = readlink(self, buf, PATH_MAX); if (len >= 0) { buf[len] = '\0'; /* readlink doesn't nul terminate */ - exec_path = strdup(buf); + exec_path = JLI_StringDup(buf); } } #else /* !__sun && !__linux */ @@ -1091,8 +1046,7 @@ void PrintMachineDependentOptions() { return; } -#ifndef GAMMA /* gamma launcher does not have ergonomics */ - +#ifndef GAMMA /* * The following methods (down to ServerClassMachine()) answer * the question about whether a machine is a "server-class" @@ -1164,7 +1118,7 @@ solaris_sparc_ServerClassMachine(void) { } } if (_launcher_debug) { - printf("solaris_" ARCH "_ServerClassMachine: %s\n", + printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE")); } return result; @@ -1262,7 +1216,6 @@ get_cpuid(uint32_t arg, uint32_t value_of_edx = 0; __asm__ volatile (/* Instructions */ /* ebx is callee-save, so push it */ - /* even though it's in the clobbers section */ " pushl %%ebx \n" " movl %4, %%eax \n" " cpuid \n" @@ -1281,7 +1234,7 @@ get_cpuid(uint32_t arg, : /* Inputs */ "m" (arg) : /* Clobbers */ - "%eax", "%ebx", "%ecx", "%edx" + "%eax", "%ecx", "%edx" ); *eaxp = value_of_eax; *ebxp = value_of_ebx; @@ -1461,7 +1414,7 @@ solaris_i586_ServerClassMachine(void) { } } if (_launcher_debug) { - printf("solaris_" ARCH "_ServerClassMachine: %s\n", + printf("solaris_" LIBARCHNAME "_ServerClassMachine: %s\n", (result == JNI_TRUE ? "true" : "false")); } return result; @@ -1494,7 +1447,7 @@ linux_i586_ServerClassMachine(void) { } } if (_launcher_debug) { - printf("linux_" ARCH "_ServerClassMachine: %s\n", + printf("linux_" LIBARCHNAME "_ServerClassMachine: %s\n", (result == JNI_TRUE ? "true" : "false")); } return result; @@ -1506,7 +1459,11 @@ linux_i586_ServerClassMachine(void) { jboolean ServerClassMachine(void) { jboolean result = JNI_FALSE; -#if defined(__sun) && defined(__sparc) +#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE) + result = JNI_FALSE; +#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE) + result = JNI_TRUE; +#elif defined(__sun) && defined(__sparc) result = solaris_sparc_ServerClassMachine(); #elif defined(__sun) && defined(i586) result = solaris_i586_ServerClassMachine(); @@ -1521,10 +1478,6 @@ ServerClassMachine(void) { return result; } -#endif /* ifndef GAMMA */ - -#ifndef GAMMA /* gamma launcher does not choose JDK/JRE/JVM */ - /* * Since using the file system as a registry is a bit risky, perform * additional sanity checks on the identified directory to validate @@ -1591,13 +1544,13 @@ static char else if (strncmp(dp->d_name, "j2sdk", 5) == 0) offset = 5; if (offset > 0) { - if ((acceptable_release(dp->d_name + offset, + if ((JLI_AcceptableRelease(dp->d_name + offset, info->jre_version)) && CheckSanity(dirname, dp->d_name)) - if ((best == NULL) || (exact_version_id( + if ((best == NULL) || (JLI_ExactVersionId( dp->d_name + offset, best + best_offset) > 0)) { if (best != NULL) - free(best); - best = strdup(dp->d_name); + JLI_MemFree(best); + best = JLI_StringDup(dp->d_name); best_offset = offset; } } @@ -1607,9 +1560,9 @@ static char if (best == NULL) return (NULL); else { - ret_str = MemAlloc(strlen(dirname) + strlen(best) + 2); + ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2); ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best); - free(best); + JLI_MemFree(best); return (ret_str); } } @@ -1636,16 +1589,17 @@ LocateJRE(manifest_info* info) * Start by getting JAVA_VERSION_PATH */ if (info->jre_restrict_search) - path = strdup(system_dir); + path = JLI_StringDup(system_dir); else if ((path = getenv("JAVA_VERSION_PATH")) != NULL) - path = strdup(path); + path = JLI_StringDup(path); else if ((home = getenv("HOME")) != NULL) { - path = (char *)MemAlloc(strlen(home) + 13); + path = (char *)JLI_MemAlloc(strlen(home) + strlen(system_dir) + + strlen(user_dir) + 2); path = strcat(strcat(strcat(strcpy(path, home), user_dir), ":"), system_dir); } else - path = strdup(system_dir); + path = JLI_StringDup(system_dir); /* * Step through each directory on the path. Terminate the scan with @@ -1662,7 +1616,7 @@ LocateJRE(manifest_info* info) if (dp != NULL) dp++; } - free(path); + JLI_MemFree(path); return (target); } @@ -1740,16 +1694,19 @@ ExecJRE(char *jre, char **argv) argv[0] = progname; if (_launcher_debug) { int i; - printf("execv(\"%s\"", wanted); - for (i = 0; argv[i] != NULL; i++) - printf(", \"%s\"", argv[i]); - printf(")\n"); + printf("ReExec Command: %s (%s)\n", wanted, argv[0]); + printf("ReExec Args:"); + for (i = 1; argv[i] != NULL; i++) + printf(" %s", argv[i]); + printf("\n"); } + (void)fflush(stdout); + (void)fflush(stderr); execv(wanted, argv); + perror("execv()"); fprintf(stderr, "Exec of %s failed\n", wanted); exit(1); } - #endif /* ifndef GAMMA */ /* @@ -1830,23 +1787,92 @@ UnsetEnv(char *name) { return(borrowed_unsetenv(name)); } + +/* --- Splash Screen shared library support --- */ + +static const char* SPLASHSCREEN_SO = "libsplashscreen.so"; + +static void* hSplashLib = NULL; + +void* SplashProcAddress(const char* name) { + if (!hSplashLib) { + hSplashLib = dlopen(SPLASHSCREEN_SO, RTLD_LAZY | RTLD_GLOBAL); + } + if (hSplashLib) { + void* sym = dlsym(hSplashLib, name); + return sym; + } else { + return NULL; + } +} + +void SplashFreeLibrary() { + if (hSplashLib) { + dlclose(hSplashLib); + hSplashLib = NULL; + } +} + +const char * +jlong_format_specifier() { + return "%lld"; +} + /* - * The implementation for finding classes from the bootstrap - * class loader, refer to java.h + * Block current thread and continue execution in a new thread */ -static FindClassFromBootLoader_t *findBootClass = NULL; +int +ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { + int rslt; +#ifdef __linux__ + pthread_t tid; + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); -jclass -FindBootStrapClass(JNIEnv *env, const char* classname) -{ - if (findBootClass == NULL) { - findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT, - "JVM_FindClassFromBootLoader"); - if (findBootClass == NULL) { - fprintf(stderr, "Error: could load method JVM_FindClassFromBootLoader"); - return NULL; - } - } - return findBootClass(env, classname, JNI_FALSE); + if (stack_size > 0) { + pthread_attr_setstacksize(&attr, stack_size); + } + + if (pthread_create(&tid, &attr, (void *(*)(void*))continuation, (void*)args) == 0) { + void * tmp; + pthread_join(tid, &tmp); + rslt = (int)tmp; + } else { + /* + * Continue execution in current thread if for some reason (e.g. out of + * memory/LWP) a new thread can't be created. This will likely fail + * later in continuation as JNI_CreateJavaVM needs to create quite a + * few new threads, anyway, just give it a try.. + */ + rslt = continuation(args); + } + + pthread_attr_destroy(&attr); +#else + thread_t tid; + long flags = 0; + if (thr_create(NULL, stack_size, (void *(*)(void *))continuation, args, flags, &tid) == 0) { + void * tmp; + thr_join(tid, NULL, &tmp); + rslt = (int)tmp; + } else { + /* See above. Continue in current thread if thr_create() failed */ + rslt = continuation(args); + } +#endif + return rslt; } +/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */ +#define MAX_PID_STR_SZ 20 + +void SetJavaLauncherPlatformProps() { + /* Linux only */ +#ifdef __linux__ + const char *substr = "-Dsun.java.launcher.pid="; + char *pid_prop_str = (char *)JLI_MemAlloc(strlen(substr) + MAX_PID_STR_SZ + 1); + sprintf(pid_prop_str, "%s%d", substr, getpid()); + AddOption(pid_prop_str, NULL); +#endif +} diff --git a/src/os/linux/launcher/java_md.h b/src/os/posix/launcher/java_md.h similarity index 92% rename from src/os/linux/launcher/java_md.h rename to src/os/posix/launcher/java_md.h index 8179a3c1c61ce0e3c3459821aaaff6c2e8fa6f90..ed36fd1af67a43cfa6c8d0a9940818ee88ef871e 100644 --- a/src/os/linux/launcher/java_md.h +++ b/src/os/posix/launcher/java_md.h @@ -22,11 +22,6 @@ * */ -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ - #ifndef JAVA_MD_H #define JAVA_MD_H @@ -36,10 +31,12 @@ #ifndef GAMMA #include "manifest_info.h" #endif +#include "jli_util.h" #define PATH_SEPARATOR ':' #define FILESEP "/" #define FILE_SEPARATOR '/' +#define IS_FILE_SEPARATOR(c) ((c) == '/') #ifndef MAXNAMELEN #define MAXNAMELEN PATH_MAX #endif @@ -71,7 +68,7 @@ * Function prototypes. */ #ifndef GAMMA -char *LocateJRE(manifest_info* info); +char *LocateJRE(manifest_info *info); void ExecJRE(char *jre, char **argv); #endif int UnsetEnv(char *name); diff --git a/src/os/posix/launcher/launcher.script b/src/os/posix/launcher/launcher.script new file mode 100644 index 0000000000000000000000000000000000000000..6eae75a3de21d3b24b2ebd08054b076c3a337008 --- /dev/null +++ b/src/os/posix/launcher/launcher.script @@ -0,0 +1,208 @@ +#!/bin/bash + +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 script launches HotSpot. +# +# If the first parameter is either "-gdb" or "-gud", HotSpot will be +# launched inside gdb. "-gud" means "open an Emacs window and run gdb +# inside Emacs". +# +# If the first parameter is "-dbx", HotSpot will be launched inside dbx. +# +# If the first parameter is "-valgrind", HotSpot will be launched +# inside Valgrind (http://valgrind.kde.org) using the Memcheck skin, +# and with memory leak detection enabled. This currently (2005jan19) +# requires at least Valgrind 2.3.0. -Xmx16m will also be passed as +# the first parameter to HotSpot, since lowering HotSpot's memory +# consumption makes execution inside of Valgrind *a lot* faster. +# + + +# +# User changeable parameters ------------------------------------------------ +# + +# This is the name of the gdb binary to use +if [ ! "$GDB" ] +then + GDB=gdb +fi + +# This is the name of the gdb binary to use +if [ ! "$DBX" ] +then + DBX=dbx +fi + +# This is the name of the Valgrind binary to use +if [ ! "$VALGRIND" ] +then + VALGRIND=valgrind +fi + +# This is the name of Emacs for running GUD +EMACS=emacs + +# +# End of user changeable parameters ----------------------------------------- +# + +# Make sure the paths are fully specified, i.e. they must begin with /. +SCRIPT=$(cd $(dirname $0) && pwd)/$(basename $0) +RUNDIR=$(pwd) + +# Look whether the user wants to run inside gdb +case "$1" in + -gdb) + MODE=gdb + shift + ;; + -gud) + MODE=gud + shift + ;; + -dbx) + MODE=dbx + shift + ;; + -valgrind) + MODE=valgrind + shift + ;; + *) + MODE=run + ;; +esac + +if [ "${ALT_JAVA_HOME}" = "" ]; then + if [ "${JAVA_HOME}" = "" ]; then + echo "Neither ALT_JAVA_HOME nor JAVA_HOME is set. Aborting."; + exit 1; + else + JDK=${JAVA_HOME%%/jre}; + fi +else + JDK=${ALT_JAVA_HOME%%/jre}; +fi + +# We will set the LD_LIBRARY_PATH as follows: +# o $JVMPATH (directory portion only) +# o $JRE/lib/$ARCH +# followed by the user's previous effective LD_LIBRARY_PATH, if +# any. +JRE=$JDK/jre +JAVA_HOME=$JDK +ARCH=@@LIBARCH@@ + +# Find out the absolute path to this script +MYDIR=$(cd $(dirname $SCRIPT) && pwd) + +SBP=${MYDIR}:${JRE}/lib/${ARCH} + +# Set up a suitable LD_LIBRARY_PATH + +if [ -z "$LD_LIBRARY_PATH" ] +then + LD_LIBRARY_PATH="$SBP" +else + LD_LIBRARY_PATH="$SBP:$LD_LIBRARY_PATH" +fi + +export LD_LIBRARY_PATH +export JAVA_HOME + +JPARMS="$@ $JAVA_ARGS"; + +# Locate the gamma development launcher +LAUNCHER=${MYDIR}/gamma +if [ ! -x $LAUNCHER ] ; then + echo Error: Cannot find the gamma development launcher \"$LAUNCHER\" + exit 1 +fi + +GDBSRCDIR=$MYDIR +BASEDIR=$(cd $MYDIR/../../.. && pwd) + +init_gdb() { +# Create a gdb script in case we should run inside gdb + GDBSCR=/tmp/hsl.$$ + rm -f $GDBSCR + cat >>$GDBSCR <= 22.1 + case $($EMACS -version 2> /dev/null) in + *GNU\ Emacs\ 2[23]*) + emacs_gud_cmd="gdba" + emacs_gud_args="--annotate=3" + ;; + *) + emacs_gud_cmd="gdb" + emacs_gud_args= + ;; + esac + $EMACS --eval "($emacs_gud_cmd \"$GDB $emacs_gud_args -x $GDBSCR\")"; + rm -f $GDBSCR + ;; + dbx) + $DBX -s $MYDIR/.dbxrc $LAUNCHER $JPARAMS + ;; + valgrind) + echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap + echo + $VALGRIND --tool=memcheck --leak-check=yes --num-callers=50 $LAUNCHER -Xmx16m $JPARMS + ;; + run) + LD_PRELOAD=$PRELOADING exec $LAUNCHER $JPARMS + ;; + *) + echo Error: Internal error, unknown launch mode \"$MODE\" + exit 1 + ;; +esac +RETVAL=$? +exit $RETVAL diff --git a/src/os/solaris/launcher/java.c b/src/os/solaris/launcher/java.c deleted file mode 100644 index 6e0f5507683f91d15d3d0c0d602ee280b2547d57..0000000000000000000000000000000000000000 --- a/src/os/solaris/launcher/java.c +++ /dev/null @@ -1,1842 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - * - * GAMMA: gamma launcher is much simpler than regular java launcher in that - * JVM is either statically linked in or it is installed in the - * same directory where the launcher exists, so we don't have to - * worry about choosing the right JVM based on command line flag, jar - * file and/or ergonomics. Intead of removing unused logic from source - * they are commented out with #ifndef GAMMA, hopefully it'll be easier - * to maintain this file in sync with regular JDK launcher. - */ - -/* - * Shared source for 'java' command line tool. - * - * If JAVA_ARGS is defined, then acts as a launcher for applications. For - * instance, the JDK command line tools such as javac and javadoc (see - * makefiles for more details) are built with this program. Any arguments - * prefixed with '-J' will be passed directly to the 'java' command. - */ - -#ifdef GAMMA -# ifdef JAVA_ARGS -# error Do NOT define JAVA_ARGS when building gamma launcher -# endif -# if !defined(LINK_INTO_AOUT) && !defined(LINK_INTO_LIBJVM) -# error Either LINK_INTO_AOUT or LINK_INTO_LIBJVM must be defined -# endif -#endif - -/* - * One job of the launcher is to remove command line options which the - * vm does not understand and will not process. These options include - * options which select which style of vm is run (e.g. -client and - * -server) as well as options which select the data model to use. - * Additionally, for tools which invoke an underlying vm "-J-foo" - * options are turned into "-foo" options to the vm. This option - * filtering is handled in a number of places in the launcher, some of - * it in machine-dependent code. In this file, the function - * CheckJVMType removes vm style options and TranslateDashJArgs - * removes "-J" prefixes. On unix platforms, the - * CreateExecutionEnvironment function from the unix java_md.c file - * processes and removes -d options. However, in case - * CreateExecutionEnvironment does not need to exec because - * LD_LIBRARY_PATH is set acceptably and the data model does not need - * to be changed, ParseArguments will screen out the redundant -d - * options and prevent them from being passed to the vm; this is done - * by using the machine-dependent call - * RemovableMachineDependentOption. - */ - -#include -#include -#include - -#include -#include "java.h" - -#ifndef GAMMA -#include "manifest_info.h" -#include "version_comp.h" -#endif - -#ifndef FULL_VERSION -#define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION -#endif - -/* - * The following environment variable is used to influence the behavior - * of the jre exec'd through the SelectVersion routine. The command line - * options which specify the version are not passed to the exec'd version, - * because that jre may be an older version which wouldn't recognize them. - * This environment variable is known to this (and later) version and serves - * to suppress the version selection code. This is not only for efficiency, - * but also for correctness, since any command line options have been - * removed which would cause any value found in the manifest to be used. - * This would be incorrect because the command line options are defined - * to take precedence. - * - * The value associated with this environment variable is the MainClass - * name from within the executable jar file (if any). This is strictly a - * performance enhancement to avoid re-reading the jar file manifest. - * - * A NOTE TO DEVELOPERS: For performance reasons it is important that - * the program image remain relatively small until after SelectVersion - * CreateExecutionEnvironment have finished their possibly recursive - * processing. Watch everything, but resist all temptations to use Java - * interfaces. - */ -#define ENV_ENTRY "_JAVA_VERSION_SET" - -static jboolean printVersion = JNI_FALSE; /* print and exit */ -static jboolean showVersion = JNI_FALSE; /* print but continue */ -static char *progname; -jboolean _launcher_debug = JNI_FALSE; - -/* - * List of VM options to be specified when the VM is created. - */ -static JavaVMOption *options; -static int numOptions, maxOptions; - -/* - * Prototypes for functions internal to launcher. - */ -static void AddOption(char *str, void *info); -static void SetClassPath(char *s); -static void SelectVersion(int argc, char **argv, char **main_class); -static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret); -static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, - InvocationFunctions *ifn); -static jstring NewPlatformString(JNIEnv *env, char *s); -static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); -static jclass LoadClass(JNIEnv *env, char *name); -static jstring GetMainClassName(JNIEnv *env, char *jarname); -static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv); -#ifdef GAMMA -static void SetJavaLauncherProp(void); -#endif - -#ifdef JAVA_ARGS -static void TranslateDashJArgs(int *pargc, char ***pargv); -static jboolean AddApplicationOptions(void); -#endif - -static void PrintJavaVersion(JNIEnv *env); -static void PrintUsage(void); -static jint PrintXUsage(void); - -static void SetPaths(int argc, char **argv); - -/* Maximum supported entries from jvm.cfg. */ -#define INIT_MAX_KNOWN_VMS 10 -/* Values for vmdesc.flag */ -#define VM_UNKNOWN -1 -#define VM_KNOWN 0 -#define VM_ALIASED_TO 1 -#define VM_WARN 2 -#define VM_ERROR 3 -#define VM_IF_SERVER_CLASS 4 -#define VM_IGNORE 5 -struct vmdesc { - char *name; - int flag; - char *alias; - char *server_class; -}; -static struct vmdesc *knownVMs = NULL; -static int knownVMsCount = 0; -static int knownVMsLimit = 0; - -static void GrowKnownVMs(); -static int KnownVMIndex(const char* name); -static void FreeKnownVMs(); - -jboolean ServerClassMachine(); - -/* flag which if set suppresses error messages from the launcher */ -static int noExitErrorMessage = 0; - -/* - * Entry point. - */ -int -main(int argc, char ** argv) -{ - JavaVM *vm = 0; - JNIEnv *env = 0; - char *jarfile = 0; - char *classname = 0; - char *s = 0; - char *main_class = NULL; - jstring mainClassName; - jclass mainClass; - jmethodID mainID; - jobjectArray mainArgs; - int ret; - InvocationFunctions ifn; - jlong start, end; - char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; - char ** original_argv = argv; - - /* - * Error message to print or display; by default the message will - * only be displayed in a window. - */ - char * message = "Fatal exception occurred. Program will exit."; - jboolean messageDest = JNI_FALSE; - - if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) { - _launcher_debug = JNI_TRUE; - printf("----_JAVA_LAUNCHER_DEBUG----\n"); - } - -#ifndef GAMMA - /* - * Make sure the specified version of the JRE is running. - * - * There are three things to note about the SelectVersion() routine: - * 1) If the version running isn't correct, this routine doesn't - * return (either the correct version has been exec'd or an error - * was issued). - * 2) Argc and Argv in this scope are *not* altered by this routine. - * It is the responsibility of subsequent code to ignore the - * arguments handled by this routine. - * 3) As a side-effect, the variable "main_class" is guaranteed to - * be set (if it should ever be set). This isn't exactly the - * poster child for structured programming, but it is a small - * price to pay for not processing a jar file operand twice. - * (Note: This side effect has been disabled. See comment on - * bugid 5030265 below.) - */ - SelectVersion(argc, argv, &main_class); -#endif /* ifndef GAMMA */ - - /* copy original argv */ - { - int i; - original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1)); - for(i = 0; i < argc+1; i++) - original_argv[i] = argv[i]; - } - - CreateExecutionEnvironment(&argc, &argv, - jrepath, sizeof(jrepath), - jvmpath, sizeof(jvmpath), - original_argv); - ifn.CreateJavaVM = 0; - ifn.GetDefaultJavaVMInitArgs = 0; - - if (_launcher_debug) - start = CounterGet(); - if (!LoadJavaVM(jvmpath, &ifn)) { - exit(6); - } - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to LoadJavaVM\n", - (long)(jint)Counter2Micros(end-start)); - } - -#ifdef JAVA_ARGS /* javac, jar and friends. */ - progname = "java"; -#else /* java, oldjava, javaw and friends */ -#ifdef PROGNAME - progname = PROGNAME; -#else - progname = *argv; - if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { - progname = s + 1; - } -#endif /* PROGNAME */ -#endif /* JAVA_ARGS */ - ++argv; - --argc; - -#ifdef JAVA_ARGS - /* Preprocess wrapper arguments */ - TranslateDashJArgs(&argc, &argv); - if (!AddApplicationOptions()) { - exit(1); - } -#endif - - /* Set default CLASSPATH */ - if ((s = getenv("CLASSPATH")) == 0) { - s = "."; - } -#ifndef JAVA_ARGS - SetClassPath(s); -#endif - - /* - * Parse command line options; if the return value of - * ParseArguments is false, the program should exit. - */ - if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) { - exit(ret); - } - - /* Override class path if -jar flag was specified */ - if (jarfile != 0) { - SetClassPath(jarfile); - } - - /* set the -Dsun.java.command pseudo property */ - SetJavaCommandLineProp(classname, jarfile, argc, argv); - -#ifdef GAMMA - /* Set the -Dsun.java.launcher pseudo property */ - SetJavaLauncherProp(); -#endif - - /* - * Done with all command line processing and potential re-execs so - * clean up the environment. - */ - (void)UnsetEnv(ENV_ENTRY); - - /* Initialize the virtual machine */ - - if (_launcher_debug) - start = CounterGet(); - if (!InitializeJVM(&vm, &env, &ifn)) { - ReportErrorMessage("Could not create the Java virtual machine.", - JNI_TRUE); - exit(1); - } - - if (printVersion || showVersion) { - PrintJavaVersion(env); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - if (printVersion) { - ret = 0; - message = NULL; - goto leave; - } - if (showVersion) { - fprintf(stderr, "\n"); - } - } - - /* If the user specified neither a class name nor a JAR file */ - if (jarfile == 0 && classname == 0) { - PrintUsage(); - message = NULL; - goto leave; - } - -#ifndef GAMMA - FreeKnownVMs(); /* after last possible PrintUsage() */ -#endif - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to InitializeJVM\n", - (long)(jint)Counter2Micros(end-start)); - } - - /* At this stage, argc/argv have the applications' arguments */ - if (_launcher_debug) { - int i = 0; - printf("Main-Class is '%s'\n", classname ? classname : ""); - printf("Apps' argc is %d\n", argc); - for (; i < argc; i++) { - printf(" argv[%2d] = '%s'\n", i, argv[i]); - } - } - - ret = 1; - - /* - * Get the application's main class. - * - * See bugid 5030265. The Main-Class name has already been parsed - * from the manifest, but not parsed properly for UTF-8 support. - * Hence the code here ignores the value previously extracted and - * uses the pre-existing code to reextract the value. This is - * possibly an end of release cycle expedient. However, it has - * also been discovered that passing some character sets through - * the environment has "strange" behavior on some variants of - * Windows. Hence, maybe the manifest parsing code local to the - * launcher should never be enhanced. - * - * Hence, future work should either: - * 1) Correct the local parsing code and verify that the - * Main-Class attribute gets properly passed through - * all environments, - * 2) Remove the vestages of maintaining main_class through - * the environment (and remove these comments). - */ - if (jarfile != 0) { - mainClassName = GetMainClassName(env, jarfile); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - if (mainClassName == NULL) { - const char * format = "Failed to load Main-Class manifest " - "attribute from\n%s"; - message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) * - sizeof(char)); - sprintf(message, format, jarfile); - messageDest = JNI_TRUE; - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - ReportExceptionDescription(env); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occurred */ - ReportExceptionDescription(env); - message = "Could not find the main class. Program will exit."; - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); - } else { - mainClassName = NewPlatformString(env, classname); - if (mainClassName == NULL) { - const char * format = "Failed to load Main Class: %s"; - message = (char *)MemAlloc((strlen(format) + strlen(classname)) * - sizeof(char) ); - sprintf(message, format, classname); - messageDest = JNI_TRUE; - goto leave; - } - classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0); - if (classname == NULL) { - ReportExceptionDescription(env); - goto leave; - } - mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occurred */ - ReportExceptionDescription(env); - message = "Could not find the main class. Program will exit."; - goto leave; - } - (*env)->ReleaseStringUTFChars(env, mainClassName, classname); - } - - /* Get the application's main method */ - mainID = (*env)->GetStaticMethodID(env, mainClass, "main", - "([Ljava/lang/String;)V"); - if (mainID == NULL) { - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - } else { - message = "No main method found in specified class."; - messageDest = JNI_TRUE; - } - goto leave; - } - - { /* Make sure the main method is public */ - jint mods; - jmethodID mid; - jobject obj = (*env)->ToReflectedMethod(env, mainClass, - mainID, JNI_TRUE); - - if( obj == NULL) { /* exception occurred */ - ReportExceptionDescription(env); - goto leave; - } - - mid = - (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, obj), - "getModifiers", "()I"); - if ((*env)->ExceptionOccurred(env)) { - ReportExceptionDescription(env); - goto leave; - } - - mods = (*env)->CallIntMethod(env, obj, mid); - if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */ - message = "Main method not public."; - messageDest = JNI_TRUE; - goto leave; - } - } - - /* Build argument array */ - mainArgs = NewPlatformStringArray(env, argv, argc); - if (mainArgs == NULL) { - ReportExceptionDescription(env); - goto leave; - } - - /* Invoke main method. */ - (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs); - - /* - * The launcher's exit code (in the absence of calls to - * System.exit) will be non-zero if main threw an exception. - */ - ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; - - /* - * Detach the main thread so that it appears to have ended when - * the application's main method exits. This will invoke the - * uncaught exception handler machinery if main threw an - * exception. An uncaught exception handler cannot change the - * launcher's return code except by calling System.exit. - */ - if ((*vm)->DetachCurrentThread(vm) != 0) { - message = "Could not detach main thread."; - messageDest = JNI_TRUE; - ret = 1; - goto leave; - } - - message = NULL; - - leave: - /* - * Wait for all non-daemon threads to end, then destroy the VM. - * This will actually create a trivial new Java waiter thread - * named "DestroyJavaVM", but this will be seen as a different - * thread from the one that executed main, even though they are - * the same C thread. This allows mainThread.join() and - * mainThread.isAlive() to work as expected. - */ - (*vm)->DestroyJavaVM(vm); - - if(message != NULL && !noExitErrorMessage) - ReportErrorMessage(message, messageDest); - return ret; -} - - -#ifndef GAMMA -/* - * Checks the command line options to find which JVM type was - * specified. If no command line option was given for the JVM type, - * the default type is used. The environment variable - * JDK_ALTERNATE_VM and the command line option -XXaltjvm= are also - * checked as ways of specifying which JVM type to invoke. - */ -char * -CheckJvmType(int *pargc, char ***argv, jboolean speculative) { - int i, argi; - int argc; - char **newArgv; - int newArgvIdx = 0; - int isVMType; - int jvmidx = -1; - char *jvmtype = getenv("JDK_ALTERNATE_VM"); - - argc = *pargc; - - /* To make things simpler we always copy the argv array */ - newArgv = MemAlloc((argc + 1) * sizeof(char *)); - - /* The program name is always present */ - newArgv[newArgvIdx++] = (*argv)[0]; - - for (argi = 1; argi < argc; argi++) { - char *arg = (*argv)[argi]; - isVMType = 0; - -#ifdef JAVA_ARGS - if (arg[0] != '-') { - newArgv[newArgvIdx++] = arg; - continue; - } -#else - if (strcmp(arg, "-classpath") == 0 || - strcmp(arg, "-cp") == 0) { - newArgv[newArgvIdx++] = arg; - argi++; - if (argi < argc) { - newArgv[newArgvIdx++] = (*argv)[argi]; - } - continue; - } - if (arg[0] != '-') break; -#endif - - /* Did the user pass an explicit VM type? */ - i = KnownVMIndex(arg); - if (i >= 0) { - jvmtype = knownVMs[jvmidx = i].name + 1; /* skip the - */ - isVMType = 1; - *pargc = *pargc - 1; - } - - /* Did the user specify an "alternate" VM? */ - else if (strncmp(arg, "-XXaltjvm=", 10) == 0 || strncmp(arg, "-J-XXaltjvm=", 12) == 0) { - isVMType = 1; - jvmtype = arg+((arg[1]=='X')? 10 : 12); - jvmidx = -1; - } - - if (!isVMType) { - newArgv[newArgvIdx++] = arg; - } - } - - /* - * Finish copying the arguments if we aborted the above loop. - * NOTE that if we aborted via "break" then we did NOT copy the - * last argument above, and in addition argi will be less than - * argc. - */ - while (argi < argc) { - newArgv[newArgvIdx++] = (*argv)[argi]; - argi++; - } - - /* argv is null-terminated */ - newArgv[newArgvIdx] = 0; - - /* Copy back argv */ - *argv = newArgv; - *pargc = newArgvIdx; - - /* use the default VM type if not specified (no alias processing) */ - if (jvmtype == NULL) { - char* result = knownVMs[0].name+1; - /* Use a different VM type if we are on a server class machine? */ - if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) && - (ServerClassMachine() == JNI_TRUE)) { - result = knownVMs[0].server_class+1; - } - if (_launcher_debug) { - printf("Default VM: %s\n", result); - } - return result; - } - - /* if using an alternate VM, no alias processing */ - if (jvmidx < 0) - return jvmtype; - - /* Resolve aliases first */ - { - int loopCount = 0; - while (knownVMs[jvmidx].flag == VM_ALIASED_TO) { - int nextIdx = KnownVMIndex(knownVMs[jvmidx].alias); - - if (loopCount > knownVMsCount) { - if (!speculative) { - ReportErrorMessage("Error: Corrupt jvm.cfg file; cycle in alias list.", - JNI_TRUE); - exit(1); - } else { - return "ERROR"; - /* break; */ - } - } - - if (nextIdx < 0) { - if (!speculative) { - ReportErrorMessage2("Error: Unable to resolve VM alias %s", - knownVMs[jvmidx].alias, JNI_TRUE); - exit(1); - } else { - return "ERROR"; - } - } - jvmidx = nextIdx; - jvmtype = knownVMs[jvmidx].name+1; - loopCount++; - } - } - - switch (knownVMs[jvmidx].flag) { - case VM_WARN: - if (!speculative) { - fprintf(stderr, "Warning: %s VM not supported; %s VM will be used\n", - jvmtype, knownVMs[0].name + 1); - } - /* fall through */ - case VM_IGNORE: - jvmtype = knownVMs[jvmidx=0].name + 1; - /* fall through */ - case VM_KNOWN: - break; - case VM_ERROR: - if (!speculative) { - ReportErrorMessage2("Error: %s VM not supported", jvmtype, JNI_TRUE); - exit(1); - } else { - return "ERROR"; - } - } - - return jvmtype; -} -#endif /* ifndef GAMMA */ - -/* - * Adds a new VM option with the given given name and value. - */ -static void -AddOption(char *str, void *info) -{ - /* - * Expand options array if needed to accommodate at least one more - * VM option. - */ - if (numOptions >= maxOptions) { - if (options == 0) { - maxOptions = 4; - options = MemAlloc(maxOptions * sizeof(JavaVMOption)); - } else { - JavaVMOption *tmp; - maxOptions *= 2; - tmp = MemAlloc(maxOptions * sizeof(JavaVMOption)); - memcpy(tmp, options, numOptions * sizeof(JavaVMOption)); - free(options); - options = tmp; - } - } - options[numOptions].optionString = str; - options[numOptions++].extraInfo = info; -} - -static void -SetClassPath(char *s) -{ - char *def = MemAlloc(strlen(s) + 40); - sprintf(def, "-Djava.class.path=%s", s); - AddOption(def, NULL); -} - -#ifndef GAMMA -/* - * The SelectVersion() routine ensures that an appropriate version of - * the JRE is running. The specification for the appropriate version - * is obtained from either the manifest of a jar file (preferred) or - * from command line options. - */ -static void -SelectVersion(int argc, char **argv, char **main_class) -{ - char *arg; - char **new_argv; - char **new_argp; - char *operand; - char *version = NULL; - char *jre = NULL; - int jarflag = 0; - int restrict_search = -1; /* -1 implies not known */ - manifest_info info; - char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "="; - char *env_in; - int res; - - /* - * If the version has already been selected, set *main_class - * with the value passed through the environment (if any) and - * simply return. - */ - if ((env_in = getenv(ENV_ENTRY)) != NULL) { - if (*env_in != '\0') - *main_class = strdup(env_in); - return; - } - - /* - * Scan through the arguments for options relevant to multiple JRE - * support. For reference, the command line syntax is defined as: - * - * SYNOPSIS - * java [options] class [argument...] - * - * java [options] -jar file.jar [argument...] - * - * As the scan is performed, make a copy of the argument list with - * the version specification options (new to 1.5) removed, so that - * a version less than 1.5 can be exec'd. - */ - new_argv = MemAlloc((argc + 1) * sizeof(char*)); - new_argv[0] = argv[0]; - new_argp = &new_argv[1]; - argc--; - argv++; - while ((arg = *argv) != 0 && *arg == '-') { - if (strncmp(arg, "-version:", 9) == 0) { - version = arg + 9; - } else if (strcmp(arg, "-jre-restrict-search") == 0) { - restrict_search = 1; - } else if (strcmp(arg, "-no-jre-restrict-search") == 0) { - restrict_search = 0; - } else { - if (strcmp(arg, "-jar") == 0) - jarflag = 1; - /* deal with "unfortunate" classpath syntax */ - if ((strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) && - (argc >= 2)) { - *new_argp++ = arg; - argc--; - argv++; - arg = *argv; - } - *new_argp++ = arg; - } - argc--; - argv++; - } - if (argc <= 0) { /* No operand? Possibly legit with -[full]version */ - operand = NULL; - } else { - argc--; - *new_argp++ = operand = *argv++; - } - while (argc-- > 0) /* Copy over [argument...] */ - *new_argp++ = *argv++; - *new_argp = NULL; - - /* - * If there is a jar file, read the manifest. If the jarfile can't be - * read, the manifest can't be read from the jar file, or the manifest - * is corrupt, issue the appropriate error messages and exit. - * - * Even if there isn't a jar file, construct a manifest_info structure - * containing the command line information. It's a convenient way to carry - * this data around. - */ - if (jarflag && operand) { - if ((res = parse_manifest(operand, &info)) != 0) { - if (res == -1) - ReportErrorMessage2("Unable to access jarfile %s", - operand, JNI_TRUE); - else - ReportErrorMessage2("Invalid or corrupt jarfile %s", - operand, JNI_TRUE); - exit(1); - } - } else { - info.manifest_version = NULL; - info.main_class = NULL; - info.jre_version = NULL; - info.jre_restrict_search = 0; - } - - /* - * The JRE-Version and JRE-Restrict-Search values (if any) from the - * manifest are overwritten by any specified on the command line. - */ - if (version != NULL) - info.jre_version = version; - if (restrict_search != -1) - info.jre_restrict_search = restrict_search; - - /* - * "Valid" returns (other than unrecoverable errors) follow. Set - * main_class as a side-effect of this routine. - */ - if (info.main_class != NULL) - *main_class = strdup(info.main_class); - - /* - * If no version selection information is found either on the command - * line or in the manifest, simply return. - */ - if (info.jre_version == NULL) { - free_manifest(); - free(new_argv); - return; - } - - /* - * Check for correct syntax of the version specification (JSR 56). - */ - if (!valid_version_string(info.jre_version)) { - ReportErrorMessage2("Syntax error in version specification \"%s\"", - info.jre_version, JNI_TRUE); - exit(1); - } - - /* - * Find the appropriate JVM on the system. Just to be as forgiving as - * possible, if the standard algorithms don't locate an appropriate - * jre, check to see if the one running will satisfy the requirements. - * This can happen on systems which haven't been set-up for multiple - * JRE support. - */ - jre = LocateJRE(&info); - if (_launcher_debug) - printf("JRE-Version = %s, JRE-Restrict-Search = %s Selected = %s\n", - (info.jre_version?info.jre_version:"null"), - (info.jre_restrict_search?"true":"false"), (jre?jre:"null")); - if (jre == NULL) { - if (acceptable_release(FULL_VERSION, info.jre_version)) { - free_manifest(); - free(new_argv); - return; - } else { - ReportErrorMessage2( - "Unable to locate JRE meeting specification \"%s\"", - info.jre_version, JNI_TRUE); - exit(1); - } - } - - /* - * If I'm not the chosen one, exec the chosen one. Returning from - * ExecJRE indicates that I am indeed the chosen one. - * - * The private environment variable _JAVA_VERSION_SET is used to - * prevent the chosen one from re-reading the manifest file and - * using the values found within to override the (potential) command - * line flags stripped from argv (because the target may not - * understand them). Passing the MainClass value is an optimization - * to avoid locating, expanding and parsing the manifest extra - * times. - */ - if (info.main_class != NULL) - (void)strcat(env_entry, info.main_class); - (void)putenv(env_entry); - ExecJRE(jre, new_argv); - free_manifest(); - free(new_argv); - return; -} -#endif /* ifndef GAMMA */ - -/* - * Parses command line arguments. Returns JNI_FALSE if launcher - * should exit without starting vm (e.g. certain version and usage - * options); returns JNI_TRUE if vm needs to be started to process - * given options. *pret (the launcher process return value) is set to - * 0 for a normal exit. - */ -static jboolean -ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret) -{ - int argc = *pargc; - char **argv = *pargv; - jboolean jarflag = JNI_FALSE; - char *arg; - - *pret = 1; - while ((arg = *argv) != 0 && *arg == '-') { - argv++; --argc; - if (strcmp(arg, "-classpath") == 0 || strcmp(arg, "-cp") == 0) { - if (argc < 1) { - ReportErrorMessage2("%s requires class path specification", - arg, JNI_TRUE); - PrintUsage(); - return JNI_FALSE; - } - SetClassPath(*argv); - argv++; --argc; - } else if (strcmp(arg, "-jar") == 0) { - jarflag = JNI_TRUE; - } else if (strcmp(arg, "-help") == 0 || - strcmp(arg, "-h") == 0 || - strcmp(arg, "-?") == 0) { - PrintUsage(); - *pret = 0; - return JNI_FALSE; - } else if (strcmp(arg, "-version") == 0) { - printVersion = JNI_TRUE; - return JNI_TRUE; - } else if (strcmp(arg, "-showversion") == 0) { - showVersion = JNI_TRUE; - } else if (strcmp(arg, "-X") == 0) { - *pret = PrintXUsage(); - return JNI_FALSE; -/* - * The following case provide backward compatibility with old-style - * command line options. - */ - } else if (strcmp(arg, "-fullversion") == 0) { - fprintf(stderr, "%s full version \"%s\"\n", progname, - FULL_VERSION); - *pret = 0; - return JNI_FALSE; - } else if (strcmp(arg, "-verbosegc") == 0) { - AddOption("-verbose:gc", NULL); - } else if (strcmp(arg, "-t") == 0) { - AddOption("-Xt", NULL); - } else if (strcmp(arg, "-tm") == 0) { - AddOption("-Xtm", NULL); - } else if (strcmp(arg, "-debug") == 0) { - AddOption("-Xdebug", NULL); - } else if (strcmp(arg, "-noclassgc") == 0) { - AddOption("-Xnoclassgc", NULL); - } else if (strcmp(arg, "-Xfuture") == 0) { - AddOption("-Xverify:all", NULL); - } else if (strcmp(arg, "-verify") == 0) { - AddOption("-Xverify:all", NULL); - } else if (strcmp(arg, "-verifyremote") == 0) { - AddOption("-Xverify:remote", NULL); - } else if (strcmp(arg, "-noverify") == 0) { - AddOption("-Xverify:none", NULL); - } else if (strcmp(arg, "-XXsuppressExitMessage") == 0) { - noExitErrorMessage = 1; - } else if (strncmp(arg, "-prof", 5) == 0) { - char *p = arg + 5; - char *tmp = MemAlloc(strlen(arg) + 50); - if (*p) { - sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1); - } else { - sprintf(tmp, "-Xrunhprof:cpu=old,file=java.prof"); - } - AddOption(tmp, NULL); - } else if (strncmp(arg, "-ss", 3) == 0 || - strncmp(arg, "-oss", 4) == 0 || - strncmp(arg, "-ms", 3) == 0 || - strncmp(arg, "-mx", 3) == 0) { - char *tmp = MemAlloc(strlen(arg) + 6); - sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ - AddOption(tmp, NULL); - } else if (strcmp(arg, "-checksource") == 0 || - strcmp(arg, "-cs") == 0 || - strcmp(arg, "-noasyncgc") == 0) { - /* No longer supported */ - fprintf(stderr, - "Warning: %s option is no longer supported.\n", - arg); - } else if (strncmp(arg, "-version:", 9) == 0 || - strcmp(arg, "-no-jre-restrict-search") == 0 || - strcmp(arg, "-jre-restrict-search") == 0) { - ; /* Ignore machine independent options already handled */ - } else if (RemovableMachineDependentOption(arg) ) { - ; /* Do not pass option to vm. */ - } - else { - AddOption(arg, NULL); - } - } - - if (--argc >= 0) { - if (jarflag) { - *pjarfile = *argv++; - *pclassname = 0; - } else { - *pjarfile = 0; - *pclassname = *argv++; - } - *pargc = argc; - *pargv = argv; - } - - return JNI_TRUE; -} - -/* - * Initializes the Java Virtual Machine. Also frees options array when - * finished. - */ -static jboolean -InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) -{ - JavaVMInitArgs args; - jint r; - - memset(&args, 0, sizeof(args)); - args.version = JNI_VERSION_1_2; - args.nOptions = numOptions; - args.options = options; - args.ignoreUnrecognized = JNI_FALSE; - - if (_launcher_debug) { - int i = 0; - printf("JavaVM args:\n "); - printf("version 0x%08lx, ", (long)args.version); - printf("ignoreUnrecognized is %s, ", - args.ignoreUnrecognized ? "JNI_TRUE" : "JNI_FALSE"); - printf("nOptions is %ld\n", (long)args.nOptions); - for (i = 0; i < numOptions; i++) - printf(" option[%2d] = '%s'\n", - i, args.options[i].optionString); - } - - r = ifn->CreateJavaVM(pvm, (void **)penv, &args); - free(options); - return r == JNI_OK; -} - - -#define NULL_CHECK0(e) if ((e) == 0) return 0 -#define NULL_CHECK(e) if ((e) == 0) return - -/* - * Returns a pointer to a block of at least 'size' bytes of memory. - * Prints error message and exits if the memory could not be allocated. - */ -void * -MemAlloc(size_t size) -{ - void *p = malloc(size); - if (p == 0) { - perror("malloc"); - exit(1); - } - return p; -} - -static jstring platformEncoding = NULL; -static jstring getPlatformEncoding(JNIEnv *env) { - if (platformEncoding == NULL) { - jstring propname = (*env)->NewStringUTF(env, "sun.jnu.encoding"); - if (propname) { - jclass cls; - jmethodID mid; - NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System")); - NULL_CHECK0 (mid = (*env)->GetStaticMethodID( - env, cls, - "getProperty", - "(Ljava/lang/String;)Ljava/lang/String;")); - platformEncoding = (*env)->CallStaticObjectMethod ( - env, cls, mid, propname); - } - } - return platformEncoding; -} - -static jboolean isEncodingSupported(JNIEnv *env, jstring enc) { - jclass cls; - jmethodID mid; - NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset")); - NULL_CHECK0 (mid = (*env)->GetStaticMethodID( - env, cls, - "isSupported", - "(Ljava/lang/String;)Z")); - return (jboolean)(*env)->CallStaticObjectMethod (env, cls, mid, enc); -} - -/* - * Returns a new Java string object for the specified platform string. - */ -static jstring -NewPlatformString(JNIEnv *env, char *s) -{ - int len = (int)strlen(s); - jclass cls; - jmethodID mid; - jbyteArray ary; - jstring enc; - - if (s == NULL) - return 0; - enc = getPlatformEncoding(env); - - ary = (*env)->NewByteArray(env, len); - if (ary != 0) { - jstring str = 0; - (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); - if (!(*env)->ExceptionOccurred(env)) { -#ifdef GAMMA - /* We support running JVM with older JDK, so here we have to deal */ - /* with the case that sun.jnu.encoding is undefined (enc == NULL) */ - if (enc != NULL && isEncodingSupported(env, enc) == JNI_TRUE) { -#else - if (isEncodingSupported(env, enc) == JNI_TRUE) { -#endif - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "([BLjava/lang/String;)V")); - str = (*env)->NewObject(env, cls, mid, ary, enc); - } else { - /*If the encoding specified in sun.jnu.encoding is not - endorsed by "Charset.isSupported" we have to fall back - to use String(byte[]) explicitly here without specifying - the encoding name, in which the StringCoding class will - pickup the iso-8859-1 as the fallback converter for us. - */ - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "([B)V")); - str = (*env)->NewObject(env, cls, mid, ary); - } - (*env)->DeleteLocalRef(env, ary); - return str; - } - } - return 0; -} - -/* - * Returns a new array of Java string objects for the specified - * array of platform strings. - */ -static jobjectArray -NewPlatformStringArray(JNIEnv *env, char **strv, int strc) -{ - jarray cls; - jarray ary; - int i; - - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); - NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); - for (i = 0; i < strc; i++) { - jstring str = NewPlatformString(env, *strv++); - NULL_CHECK0(str); - (*env)->SetObjectArrayElement(env, ary, i, str); - (*env)->DeleteLocalRef(env, str); - } - return ary; -} - -/* - * Loads a class, convert the '.' to '/'. - */ -static jclass -LoadClass(JNIEnv *env, char *name) -{ - char *buf = MemAlloc(strlen(name) + 1); - char *s = buf, *t = name, c; - jclass cls; - jlong start, end; - - if (_launcher_debug) - start = CounterGet(); - - do { - c = *t++; - *s++ = (c == '.') ? '/' : c; - } while (c != '\0'); - // use the application class loader for the main-class - cls = (*env)->FindClass(env, buf); - free(buf); - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to load main class\n", - (long)(jint)Counter2Micros(end-start)); - printf("----_JAVA_LAUNCHER_DEBUG----\n"); - } - - return cls; -} - - -/* - * Returns the main class name for the specified jar file. - */ -static jstring -GetMainClassName(JNIEnv *env, char *jarname) -{ -#define MAIN_CLASS "Main-Class" - jclass cls; - jmethodID mid; - jobject jar, man, attr; - jstring str, result = 0; - - NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile")); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", - "(Ljava/lang/String;)V")); - NULL_CHECK0(str = NewPlatformString(env, jarname)); - NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); - NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", - "()Ljava/util/jar/Manifest;")); - man = (*env)->CallObjectMethod(env, jar, mid); - if (man != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, man), - "getMainAttributes", - "()Ljava/util/jar/Attributes;")); - attr = (*env)->CallObjectMethod(env, man, mid); - if (attr != 0) { - NULL_CHECK0(mid = (*env)->GetMethodID(env, - (*env)->GetObjectClass(env, attr), - "getValue", - "(Ljava/lang/String;)Ljava/lang/String;")); - NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); - result = (*env)->CallObjectMethod(env, attr, mid, str); - } - } - return result; -} - -#ifdef JAVA_ARGS -static char *java_args[] = JAVA_ARGS; -static char *app_classpath[] = APP_CLASSPATH; - -/* - * For tools convert 'javac -J-ms32m' to 'java -ms32m ...' - */ -static void -TranslateDashJArgs(int *pargc, char ***pargv) -{ - const int NUM_ARGS = (sizeof(java_args) / sizeof(char *)); - int argc = *pargc; - char **argv = *pargv; - int nargc = argc + NUM_ARGS; - char **nargv = MemAlloc((nargc + 1) * sizeof(char *)); - int i; - - *pargc = nargc; - *pargv = nargv; - - /* Copy the VM arguments (i.e. prefixed with -J) */ - for (i = 0; i < NUM_ARGS; i++) { - char *arg = java_args[i]; - if (arg[0] == '-' && arg[1] == 'J') { - *nargv++ = arg + 2; - } - } - - for (i = 0; i < argc; i++) { - char *arg = argv[i]; - if (arg[0] == '-' && arg[1] == 'J') { - if (arg[2] == '\0') { - ReportErrorMessage("Error: the -J option should not be " - "followed by a space.", JNI_TRUE); - exit(1); - } - *nargv++ = arg + 2; - } - } - - /* Copy the rest of the arguments */ - for (i = 0; i < NUM_ARGS; i++) { - char *arg = java_args[i]; - if (arg[0] != '-' || arg[1] != 'J') { - *nargv++ = arg; - } - } - for (i = 0; i < argc; i++) { - char *arg = argv[i]; - if (arg[0] != '-' || arg[1] != 'J') { - *nargv++ = arg; - } - } - *nargv = 0; -} - -/* - * For our tools, we try to add 3 VM options: - * -Denv.class.path= - * -Dapplication.home= - * -Djava.class.path= - * is the user's setting of CLASSPATH -- for instance the user - * tells javac where to find binary classes through this environment - * variable. Notice that users will be able to compile against our - * tools classes (sun.tools.javac.Main) only if they explicitly add - * tools.jar to CLASSPATH. - * is the directory where the application is installed. - * is the classpath to where our apps' classfiles are. - */ -static jboolean -AddApplicationOptions() -{ - const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *)); - char *s, *envcp, *appcp, *apphome; - char home[MAXPATHLEN]; /* application home */ - char separator[] = { PATH_SEPARATOR, '\0' }; - int size, i; - int strlenHome; - - s = getenv("CLASSPATH"); - if (s) { - /* 40 for -Denv.class.path= */ - envcp = (char *)MemAlloc(strlen(s) + 40); - sprintf(envcp, "-Denv.class.path=%s", s); - AddOption(envcp, NULL); - } - - if (!GetApplicationHome(home, sizeof(home))) { - ReportErrorMessage("Can't determine application home", JNI_TRUE); - return JNI_FALSE; - } - - /* 40 for '-Dapplication.home=' */ - apphome = (char *)MemAlloc(strlen(home) + 40); - sprintf(apphome, "-Dapplication.home=%s", home); - AddOption(apphome, NULL); - - /* How big is the application's classpath? */ - size = 40; /* 40: "-Djava.class.path=" */ - strlenHome = (int)strlen(home); - for (i = 0; i < NUM_APP_CLASSPATH; i++) { - size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */ - } - appcp = (char *)MemAlloc(size + 1); - strcpy(appcp, "-Djava.class.path="); - for (i = 0; i < NUM_APP_CLASSPATH; i++) { - strcat(appcp, home); /* c:\program files\myapp */ - strcat(appcp, app_classpath[i]); /* \lib\myapp.jar */ - strcat(appcp, separator); /* ; */ - } - appcp[strlen(appcp)-1] = '\0'; /* remove trailing path separator */ - AddOption(appcp, NULL); - return JNI_TRUE; -} -#endif - -/* - * inject the -Dsun.java.command pseudo property into the args structure - * this pseudo property is used in the HotSpot VM to expose the - * Java class name and arguments to the main method to the VM. The - * HotSpot VM uses this pseudo property to store the Java class name - * (or jar file name) and the arguments to the class's main method - * to the instrumentation memory region. The sun.java.command pseudo - * property is not exported by HotSpot to the Java layer. - */ -void -SetJavaCommandLineProp(char *classname, char *jarfile, - int argc, char **argv) -{ - - int i = 0; - size_t len = 0; - char* javaCommand = NULL; - char* dashDstr = "-Dsun.java.command="; - - if (classname == NULL && jarfile == NULL) { - /* unexpected, one of these should be set. just return without - * setting the property - */ - return; - } - - /* if the class name is not set, then use the jarfile name */ - if (classname == NULL) { - classname = jarfile; - } - - /* determine the amount of memory to allocate assuming - * the individual components will be space separated - */ - len = strlen(classname); - for (i = 0; i < argc; i++) { - len += strlen(argv[i]) + 1; - } - - /* allocate the memory */ - javaCommand = (char*) MemAlloc(len + strlen(dashDstr) + 1); - - /* build the -D string */ - *javaCommand = '\0'; - strcat(javaCommand, dashDstr); - strcat(javaCommand, classname); - - for (i = 0; i < argc; i++) { - /* the components of the string are space separated. In - * the case of embedded white space, the relationship of - * the white space separated components to their true - * positional arguments will be ambiguous. This issue may - * be addressed in a future release. - */ - strcat(javaCommand, " "); - strcat(javaCommand, argv[i]); - } - - AddOption(javaCommand, NULL); -} - -/* - * JVM wants to know launcher type, so tell it. - */ -#ifdef GAMMA -void SetJavaLauncherProp() { - AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL); -} -#endif - -/* - * Prints the version information from the java.version and other properties. - */ -static void -PrintJavaVersion(JNIEnv *env) -{ - jclass ver; - jmethodID print; - - NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); - NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V")); - - (*env)->CallStaticVoidMethod(env, ver, print); -} - -/* - * Prints default usage message. - */ -static void -PrintUsage(void) -{ - int i; - - fprintf(stdout, - "Usage: %s [-options] class [args...]\n" - " (to execute a class)\n" - " or %s [-options] -jar jarfile [args...]\n" - " (to execute a jar file)\n" - "\n" - "where options include:\n", - progname, - progname); - -#ifndef GAMMA - PrintMachineDependentOptions(); - - if ((knownVMs[0].flag == VM_KNOWN) || - (knownVMs[0].flag == VM_IF_SERVER_CLASS)) { - fprintf(stdout, " %s\t to select the \"%s\" VM\n", - knownVMs[0].name, knownVMs[0].name+1); - } - for (i=1; i\n" -" -classpath \n" -" A %c separated list of directories, JAR archives,\n" -" and ZIP archives to search for class files.\n" -" -D=\n" -" set a system property\n" -" -verbose[:class|gc|jni]\n" -" enable verbose output\n" -" -version print product version and exit\n" -" -version:\n" -" require the specified version to run\n" -" -showversion print product version and continue\n" -" -jre-restrict-search | -jre-no-restrict-search\n" -" include/exclude user private JREs in the version search\n" -" -? -help print this help message\n" -" -X print help on non-standard options\n" -" -ea[:...|:]\n" -" -enableassertions[:...|:]\n" -" enable assertions\n" -" -da[:...|:]\n" -" -disableassertions[:...|:]\n" -" disable assertions\n" -" -esa | -enablesystemassertions\n" -" enable system assertions\n" -" -dsa | -disablesystemassertions\n" -" disable system assertions\n" -" -agentlib:[=]\n" -" load native agent library , e.g. -agentlib:hprof\n" -" see also, -agentlib:jdwp=help and -agentlib:hprof=help\n" -" -agentpath:[=]\n" -" load native agent library by full pathname\n" -" -javaagent:[=]\n" -" load Java programming language agent, see java.lang.instrument\n" - - ,PATH_SEPARATOR); -} - -/* - * Print usage message for -X options. - */ -static jint -PrintXUsage(void) -{ - char path[MAXPATHLEN]; - char buf[128]; - size_t n; - FILE *fp; - - GetXUsagePath(path, sizeof(path)); - fp = fopen(path, "r"); - if (fp == 0) { - fprintf(stderr, "Can't open %s\n", path); - return 1; - } - while ((n = fread(buf, 1, sizeof(buf), fp)) != 0) { - fwrite(buf, 1, n, stdout); - } - fclose(fp); - return 0; -} - -#ifndef GAMMA - -/* - * Read the jvm.cfg file and fill the knownJVMs[] array. - * - * The functionality of the jvm.cfg file is subject to change without - * notice and the mechanism will be removed in the future. - * - * The lexical structure of the jvm.cfg file is as follows: - * - * jvmcfg := { vmLine } - * vmLine := knownLine - * | aliasLine - * | warnLine - * | ignoreLine - * | errorLine - * | predicateLine - * | commentLine - * knownLine := flag "KNOWN" EOL - * warnLine := flag "WARN" EOL - * ignoreLine := flag "IGNORE" EOL - * errorLine := flag "ERROR" EOL - * aliasLine := flag "ALIASED_TO" flag EOL - * predicateLine := flag "IF_SERVER_CLASS" flag EOL - * commentLine := "#" text EOL - * flag := "-" identifier - * - * The semantics are that when someone specifies a flag on the command line: - * - if the flag appears on a knownLine, then the identifier is used as - * the name of the directory holding the JVM library (the name of the JVM). - * - if the flag appears as the first flag on an aliasLine, the identifier - * of the second flag is used as the name of the JVM. - * - if the flag appears on a warnLine, the identifier is used as the - * name of the JVM, but a warning is generated. - * - if the flag appears on an ignoreLine, the identifier is recognized as the - * name of a JVM, but the identifier is ignored and the default vm used - * - if the flag appears on an errorLine, an error is generated. - * - if the flag appears as the first flag on a predicateLine, and - * the machine on which you are running passes the predicate indicated, - * then the identifier of the second flag is used as the name of the JVM, - * otherwise the identifier of the first flag is used as the name of the JVM. - * If no flag is given on the command line, the first vmLine of the jvm.cfg - * file determines the name of the JVM. - * PredicateLines are only interpreted on first vmLine of a jvm.cfg file, - * since they only make sense if someone hasn't specified the name of the - * JVM on the command line. - * - * The intent of the jvm.cfg file is to allow several JVM libraries to - * be installed in different subdirectories of a single JRE installation, - * for space-savings and convenience in testing. - * The intent is explicitly not to provide a full aliasing or predicate - * mechanism. - */ -jint -ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) -{ - FILE *jvmCfg; - char jvmCfgName[MAXPATHLEN+20]; - char line[MAXPATHLEN+20]; - int cnt = 0; - int lineno = 0; - jlong start, end; - int vmType; - char *tmpPtr; - char *altVMName; - char *serverClassVMName; - static char *whiteSpace = " \t"; - if (_launcher_debug) { - start = CounterGet(); - } - - strcpy(jvmCfgName, jrepath); - strcat(jvmCfgName, FILESEP "lib" FILESEP); - strcat(jvmCfgName, arch); - strcat(jvmCfgName, FILESEP "jvm.cfg"); - - jvmCfg = fopen(jvmCfgName, "r"); - if (jvmCfg == NULL) { - if (!speculative) { - ReportErrorMessage2("Error: could not open `%s'", jvmCfgName, - JNI_TRUE); - exit(1); - } else { - return -1; - } - } - while (fgets(line, sizeof(line), jvmCfg) != NULL) { - vmType = VM_UNKNOWN; - lineno++; - if (line[0] == '#') - continue; - if (line[0] != '-') { - fprintf(stderr, "Warning: no leading - on line %d of `%s'\n", - lineno, jvmCfgName); - } - if (cnt >= knownVMsLimit) { - GrowKnownVMs(cnt); - } - line[strlen(line)-1] = '\0'; /* remove trailing newline */ - tmpPtr = line + strcspn(line, whiteSpace); - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null-terminate this string for strdup below */ - *tmpPtr++ = 0; - tmpPtr += strspn(tmpPtr, whiteSpace); - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - if (!strncmp(tmpPtr, "KNOWN", strlen("KNOWN"))) { - vmType = VM_KNOWN; - } else if (!strncmp(tmpPtr, "ALIASED_TO", strlen("ALIASED_TO"))) { - tmpPtr += strcspn(tmpPtr, whiteSpace); - if (*tmpPtr != 0) { - tmpPtr += strspn(tmpPtr, whiteSpace); - } - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing VM alias on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null terminate altVMName */ - altVMName = tmpPtr; - tmpPtr += strcspn(tmpPtr, whiteSpace); - *tmpPtr = 0; - vmType = VM_ALIASED_TO; - } - } else if (!strncmp(tmpPtr, "WARN", strlen("WARN"))) { - vmType = VM_WARN; - } else if (!strncmp(tmpPtr, "IGNORE", strlen("IGNORE"))) { - vmType = VM_IGNORE; - } else if (!strncmp(tmpPtr, "ERROR", strlen("ERROR"))) { - vmType = VM_ERROR; - } else if (!strncmp(tmpPtr, - "IF_SERVER_CLASS", - strlen("IF_SERVER_CLASS"))) { - tmpPtr += strcspn(tmpPtr, whiteSpace); - if (*tmpPtr != 0) { - tmpPtr += strspn(tmpPtr, whiteSpace); - } - if (*tmpPtr == 0) { - fprintf(stderr, "Warning: missing server class VM on line %d of `%s'\n", - lineno, jvmCfgName); - } else { - /* Null terminate server class VM name */ - serverClassVMName = tmpPtr; - tmpPtr += strcspn(tmpPtr, whiteSpace); - *tmpPtr = 0; - vmType = VM_IF_SERVER_CLASS; - } - } else { - fprintf(stderr, "Warning: unknown VM type on line %d of `%s'\n", - lineno, &jvmCfgName[0]); - vmType = VM_KNOWN; - } - } - } - - if (_launcher_debug) - printf("jvm.cfg[%d] = ->%s<-\n", cnt, line); - if (vmType != VM_UNKNOWN) { - knownVMs[cnt].name = strdup(line); - knownVMs[cnt].flag = vmType; - switch (vmType) { - default: - break; - case VM_ALIASED_TO: - knownVMs[cnt].alias = strdup(altVMName); - if (_launcher_debug) { - printf(" name: %s vmType: %s alias: %s\n", - knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias); - } - break; - case VM_IF_SERVER_CLASS: - knownVMs[cnt].server_class = strdup(serverClassVMName); - if (_launcher_debug) { - printf(" name: %s vmType: %s server_class: %s\n", - knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class); - } - break; - } - cnt++; - } - } - fclose(jvmCfg); - knownVMsCount = cnt; - - if (_launcher_debug) { - end = CounterGet(); - printf("%ld micro seconds to parse jvm.cfg\n", - (long)(jint)Counter2Micros(end-start)); - } - - return cnt; -} - - -static void -GrowKnownVMs(int minimum) -{ - struct vmdesc* newKnownVMs; - int newMax; - - newMax = (knownVMsLimit == 0 ? INIT_MAX_KNOWN_VMS : (2 * knownVMsLimit)); - if (newMax <= minimum) { - newMax = minimum; - } - newKnownVMs = (struct vmdesc*) MemAlloc(newMax * sizeof(struct vmdesc)); - if (knownVMs != NULL) { - memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc)); - } - free(knownVMs); - knownVMs = newKnownVMs; - knownVMsLimit = newMax; -} - - -/* Returns index of VM or -1 if not found */ -static int -KnownVMIndex(const char* name) -{ - int i; - if (strncmp(name, "-J", 2) == 0) name += 2; - for (i = 0; i < knownVMsCount; i++) { - if (!strcmp(name, knownVMs[i].name)) { - return i; - } - } - return -1; -} - -static void -FreeKnownVMs() -{ - int i; - for (i = 0; i < knownVMsCount; i++) { - free(knownVMs[i].name); - knownVMs[i].name = NULL; - } - free(knownVMs); -} - -#endif /* ifndef GAMMA */ diff --git a/src/os/solaris/launcher/java.h b/src/os/solaris/launcher/java.h deleted file mode 100644 index b5f3a9993f5004ad5b83f38ca6368227ef8eb7a7..0000000000000000000000000000000000000000 --- a/src/os/solaris/launcher/java.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ - -#ifndef _JAVA_H_ -#define _JAVA_H_ - -/* - * Get system specific defines. - */ -#include "jni.h" -#include "java_md.h" - -/* - * Pointers to the needed JNI invocation API, initialized by LoadJavaVM. - */ -typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args); -typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args); - -typedef struct { - CreateJavaVM_t CreateJavaVM; - GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs; -} InvocationFunctions; - -/* - * Prototypes for launcher functions in the system specific java_md.c. - */ - -jboolean -LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn); - -void -GetXUsagePath(char *buf, jint bufsize); - -jboolean -GetApplicationHome(char *buf, jint bufsize); - -const char * -GetArch(); - -void CreateExecutionEnvironment(int *_argc, - char ***_argv, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv); - -/* - * Report an error message to stderr or a window as appropriate. The - * flag always is set to JNI_TRUE if message is to be reported to both - * strerr and windows and set to JNI_FALSE if the message should only - * be sent to a window. - */ -void ReportErrorMessage(char * message, jboolean always); -void ReportErrorMessage2(char * format, char * string, jboolean always); - -/* - * Report an exception which terminates the vm to stderr or a window - * as appropriate. - */ -void ReportExceptionDescription(JNIEnv * env); - -jboolean RemovableMachineDependentOption(char * option); -void PrintMachineDependentOptions(); - -/* - * Functions defined in java.c and used in java_md.c. - */ -jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative); -char *CheckJvmType(int *argc, char ***argv, jboolean speculative); -void* MemAlloc(size_t size); - -/* - * Make launcher spit debug output. - */ -extern jboolean _launcher_debug; - -/* - * This allows for finding classes from the VM's bootstrap class loader - * directly, FindClass uses the application class loader internally, this will - * cause unnecessary searching of the classpath for the required classes. - */ -typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env, - const char *name, - jboolean throwError)); - -jclass FindBootStrapClass(JNIEnv *env, const char *classname); - -#endif /* _JAVA_H_ */ diff --git a/src/os/solaris/launcher/java_md.c b/src/os/solaris/launcher/java_md.c deleted file mode 100644 index 8675a7a9c10c8cb5d0cb547925d031aaf410e116..0000000000000000000000000000000000000000 --- a/src/os/solaris/launcher/java_md.c +++ /dev/null @@ -1,1849 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ - -#include "java.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef GAMMA -#include "manifest_info.h" -#include "version_comp.h" -#endif - -#define JVM_DLL "libjvm.so" -#define JAVA_DLL "libjava.so" - -#ifndef GAMMA /* launcher.make defines ARCH */ - -/* - * If a processor / os combination has the ability to run binaries of - * two data models and cohabitation of jre/jdk bits with both data - * models is supported, then DUAL_MODE is defined. When DUAL_MODE is - * defined, the architecture names for the narrow and wide version of - * the architecture are defined in BIG_ARCH and SMALL_ARCH. Currently - * only Solaris on sparc/sparcv9 and i586/amd64 is DUAL_MODE; linux - * i586/amd64 could be defined as DUAL_MODE but that is not the - * current policy. - */ - -#ifdef _LP64 - -# ifdef ia64 -# define ARCH "ia64" -# elif defined(amd64) -# define ARCH "amd64" -# elif defined(__sparc) -# define ARCH "sparcv9" -# else -# define ARCH "unknown" /* unknown 64-bit architecture */ -# endif - -#else /* 32-bit data model */ - -# ifdef i586 -# define ARCH "i386" -# elif defined(__sparc) -# define ARCH "sparc" -# endif - -#endif /* _LP64 */ - -#ifdef __sun -# define DUAL_MODE -# ifdef __sparc -# define BIG_ARCH "sparcv9" -# define SMALL_ARCH "sparc" -# else -# define BIG_ARCH "amd64" -# define SMALL_ARCH "i386" -# endif -# include -# include -# include -#else -# ifndef ARCH -# include -# endif -#endif - -#endif /* ifndef GAMMA */ - -/* pointer to environment */ -extern char **environ; - -#ifndef GAMMA - -/* - * A collection of useful strings. One should think of these as #define - * entries, but actual strings can be more efficient (with many compilers). - */ -#ifdef __linux__ -static const char *system_dir = "/usr/java"; -static const char *user_dir = "/java"; -#else /* Solaris */ -static const char *system_dir = "/usr/jdk"; -static const char *user_dir = "/jdk"; -#endif - -#endif /* ifndef GAMMA */ - -/* - * Flowchart of launcher execs and options processing on unix - * - * The selection of the proper vm shared library to open depends on - * several classes of command line options, including vm "flavor" - * options (-client, -server) and the data model options, -d32 and - * -d64, as well as a version specification which may have come from - * the command line or from the manifest of an executable jar file. - * The vm selection options are not passed to the running - * virtual machine; they must be screened out by the launcher. - * - * The version specification (if any) is processed first by the - * platform independent routine SelectVersion. This may result in - * the exec of the specified launcher version. - * - * Typically, the launcher execs at least once to ensure a suitable - * LD_LIBRARY_PATH is in effect for the process. The first exec - * screens out all the data model options; leaving the choice of data - * model implicit in the binary selected to run. However, in case no - * exec is done, the data model options are screened out before the vm - * is invoked. - * - * incoming argv ------------------------------ - * | | - * \|/ | - * CheckJVMType | - * (removes -client, -server, etc.) | - * \|/ - * CreateExecutionEnvironment - * (removes -d32 and -d64, - * determines desired data model, - * sets up LD_LIBRARY_PATH, - * and exec's) - * | - * -------------------------------------------- - * | - * \|/ - * exec child 1 incoming argv ----------------- - * | | - * \|/ | - * CheckJVMType | - * (removes -client, -server, etc.) | - * | \|/ - * | CreateExecutionEnvironment - * | (verifies desired data model - * | is running and acceptable - * | LD_LIBRARY_PATH; - * | no-op in child) - * | - * \|/ - * TranslateDashJArgs... - * (Prepare to pass args to vm) - * | - * | - * | - * \|/ - * ParseArguments - * (ignores -d32 and -d64, - * processes version options, - * creates argument list for vm, - * etc.) - * - */ - -static char *SetExecname(char **argv); -static char * GetExecname(); -static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize, char * arch); -static jboolean GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative); - -const char * -GetArch() -{ - static char *arch = NULL; - static char buf[12]; - if (arch) { - return arch; - } - -#ifdef ARCH - strcpy(buf, ARCH); -#else - sysinfo(SI_ARCHITECTURE, buf, sizeof(buf)); -#endif - arch = buf; - return arch; -} - -void -CreateExecutionEnvironment(int *_argcp, - char ***_argvp, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv) { - /* - * First, determine if we are running the desired data model. If we - * are running the desired data model, all the error messages - * associated with calling GetJREPath, ReadKnownVMs, etc. should be - * output. However, if we are not running the desired data model, - * some of the errors should be suppressed since it is more - * informative to issue an error message based on whether or not the - * os/processor combination has dual mode capabilities. - */ - - char *execname = NULL; - int original_argc = *_argcp; - jboolean jvmpathExists; - - /* Compute the name of the executable */ - execname = SetExecname(*_argvp); - -#ifndef GAMMA - /* Set the LD_LIBRARY_PATH environment variable, check data model - flags, and exec process, if needed */ - { - char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ - char * jvmtype = NULL; - int argc = *_argcp; - char **argv = original_argv; - - char *runpath = NULL; /* existing effective LD_LIBRARY_PATH - setting */ - - int running = /* What data model is being ILP32 => - 32 bit vm; LP64 => 64 bit vm */ -#ifdef _LP64 - 64; -#else - 32; -#endif - - int wanted = running; /* What data mode is being - asked for? Current model is - fine unless another model - is asked for */ - - char* new_runpath = NULL; /* desired new LD_LIBRARY_PATH string */ - char* newpath = NULL; /* path on new LD_LIBRARY_PATH */ - char* lastslash = NULL; - - char** newenvp = NULL; /* current environment */ - - char** newargv = NULL; - int newargc = 0; -#ifdef __sun - char* dmpath = NULL; /* data model specific LD_LIBRARY_PATH, - Solaris only */ -#endif - - /* - * Starting in 1.5, all unix platforms accept the -d32 and -d64 - * options. On platforms where only one data-model is supported - * (e.g. ia-64 Linux), using the flag for the other data model is - * an error and will terminate the program. - */ - - { /* open new scope to declare local variables */ - int i; - - newargv = (char **)MemAlloc((argc+1) * sizeof(*newargv)); - newargv[newargc++] = argv[0]; - - /* scan for data model arguments and remove from argument list; - last occurrence determines desired data model */ - for (i=1; i < argc; i++) { - - if (strcmp(argv[i], "-J-d64") == 0 || strcmp(argv[i], "-d64") == 0) { - wanted = 64; - continue; - } - if (strcmp(argv[i], "-J-d32") == 0 || strcmp(argv[i], "-d32") == 0) { - wanted = 32; - continue; - } - newargv[newargc++] = argv[i]; - -#ifdef JAVA_ARGS - if (argv[i][0] != '-') - continue; -#else - if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) { - i++; - if (i >= argc) break; - newargv[newargc++] = argv[i]; - continue; - } - if (argv[i][0] != '-') { i++; break; } -#endif - } - - /* copy rest of args [i .. argc) */ - while (i < argc) { - newargv[newargc++] = argv[i++]; - } - newargv[newargc] = NULL; - - /* - * newargv has all proper arguments here - */ - - argc = newargc; - argv = newargv; - } - - /* If the data model is not changing, it is an error if the - jvmpath does not exist */ - if (wanted == running) { - /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { - fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); - exit(2); - } - - /* Find the specified JVM type */ - if (ReadKnownVMs(jrepath, arch, JNI_FALSE) < 1) { - fprintf(stderr, "Error: no known VMs. (check for corrupt jvm.cfg file)\n"); - exit(1); - } - - jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE); - - if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) { - fprintf(stderr, "Error: no `%s' JVM at `%s'.\n", jvmtype, jvmpath); - exit(4); - } - } else { /* do the same speculatively or exit */ -#ifdef DUAL_MODE - if (running != wanted) { - /* Find out where the JRE is that we will be using. */ - if (!GetJREPath(jrepath, so_jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE)) { - goto EndDataModelSpeculate; - } - - /* - * Read in jvm.cfg for target data model and process vm - * selection options. - */ - if (ReadKnownVMs(jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), JNI_TRUE) < 1) { - goto EndDataModelSpeculate; - } - jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE); - /* exec child can do error checking on the existence of the path */ - jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, - ((wanted==64)?BIG_ARCH:SMALL_ARCH)); - - } - EndDataModelSpeculate: /* give up and let other code report error message */ - ; -#else - fprintf(stderr, "Running a %d-bit JVM is not supported on this platform.\n", wanted); - exit(1); -#endif - } - - /* - * We will set the LD_LIBRARY_PATH as follows: - * - * o $JVMPATH (directory portion only) - * o $JRE/lib/$ARCH - * o $JRE/../lib/$ARCH - * - * followed by the user's previous effective LD_LIBRARY_PATH, if - * any. - */ - -#ifdef __sun - /* - * Starting in Solaris 7, ld.so.1 supports three LD_LIBRARY_PATH - * variables: - * - * 1. LD_LIBRARY_PATH -- used for 32 and 64 bit searches if - * data-model specific variables are not set. - * - * 2. LD_LIBRARY_PATH_64 -- overrides and replaces LD_LIBRARY_PATH - * for 64-bit binaries. - * - * 3. LD_LIBRARY_PATH_32 -- overrides and replaces LD_LIBRARY_PATH - * for 32-bit binaries. - * - * The vm uses LD_LIBRARY_PATH to set the java.library.path system - * property. To shield the vm from the complication of multiple - * LD_LIBRARY_PATH variables, if the appropriate data model - * specific variable is set, we will act as if LD_LIBRARY_PATH had - * the value of the data model specific variant and the data model - * specific variant will be unset. Note that the variable for the - * *wanted* data model must be used (if it is set), not simply the - * current running data model. - */ - - switch(wanted) { - case 0: - if(running == 32) { - dmpath = getenv("LD_LIBRARY_PATH_32"); - wanted = 32; - } - else { - dmpath = getenv("LD_LIBRARY_PATH_64"); - wanted = 64; - } - break; - - case 32: - dmpath = getenv("LD_LIBRARY_PATH_32"); - break; - - case 64: - dmpath = getenv("LD_LIBRARY_PATH_64"); - break; - - default: - fprintf(stderr, "Improper value at line %d.", __LINE__); - exit(1); /* unknown value in wanted */ - break; - } - - /* - * If dmpath is NULL, the relevant data model specific variable is - * not set and normal LD_LIBRARY_PATH should be used. - */ - if( dmpath == NULL) { - runpath = getenv("LD_LIBRARY_PATH"); - } - else { - runpath = dmpath; - } -#else - /* - * If not on Solaris, assume only a single LD_LIBRARY_PATH - * variable. - */ - runpath = getenv("LD_LIBRARY_PATH"); -#endif /* __sun */ - -#ifdef __linux - /* - * On linux, if a binary is running as sgid or suid, glibc sets - * LD_LIBRARY_PATH to the empty string for security purposes. (In - * contrast, on Solaris the LD_LIBRARY_PATH variable for a - * privileged binary does not lose its settings; but the dynamic - * linker does apply more scrutiny to the path.) The launcher uses - * the value of LD_LIBRARY_PATH to prevent an exec loop. - * Therefore, if we are running sgid or suid, this function's - * setting of LD_LIBRARY_PATH will be ineffective and we should - * return from the function now. Getting the right libraries to - * be found must be handled through other mechanisms. - */ - if((getgid() != getegid()) || (getuid() != geteuid()) ) { - return; - } -#endif - - /* runpath contains current effective LD_LIBRARY_PATH setting */ - - jvmpath = strdup(jvmpath); - new_runpath = MemAlloc( ((runpath!=NULL)?strlen(runpath):0) + - 2*strlen(jrepath) + 2*strlen(arch) + - strlen(jvmpath) + 52); - newpath = new_runpath + strlen("LD_LIBRARY_PATH="); - - - /* - * Create desired LD_LIBRARY_PATH value for target data model. - */ - { - /* remove the name of the .so from the JVM path */ - lastslash = strrchr(jvmpath, '/'); - if (lastslash) - *lastslash = '\0'; - - - /* jvmpath, ((running != wanted)?((wanted==64)?"/"BIG_ARCH:"/.."):""), */ - - sprintf(new_runpath, "LD_LIBRARY_PATH=" - "%s:" - "%s/lib/%s:" - "%s/../lib/%s", - jvmpath, -#ifdef DUAL_MODE - jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH), - jrepath, ((wanted==64)?BIG_ARCH:SMALL_ARCH) -#else - jrepath, arch, - jrepath, arch -#endif - ); - - - /* - * Check to make sure that the prefix of the current path is the - * desired environment variable setting. - */ - if (runpath != NULL && - strncmp(newpath, runpath, strlen(newpath))==0 && - (runpath[strlen(newpath)] == 0 || runpath[strlen(newpath)] == ':') && - (running == wanted) /* data model does not have to be changed */ -#ifdef __sun - && (dmpath == NULL) /* data model specific variables not set */ -#endif - ) { - - return; - - } - } - - /* - * Place the desired environment setting onto the prefix of - * LD_LIBRARY_PATH. Note that this prevents any possible infinite - * loop of execv() because we test for the prefix, above. - */ - if (runpath != 0) { - strcat(new_runpath, ":"); - strcat(new_runpath, runpath); - } - - if( putenv(new_runpath) != 0) { - exit(1); /* problem allocating memory; LD_LIBRARY_PATH not set - properly */ - } - - /* - * Unix systems document that they look at LD_LIBRARY_PATH only - * once at startup, so we have to re-exec the current executable - * to get the changed environment variable to have an effect. - */ - -#ifdef __sun - /* - * If dmpath is not NULL, remove the data model specific string - * in the environment for the exec'ed child. - */ - - if( dmpath != NULL) - (void)UnsetEnv((wanted==32)?"LD_LIBRARY_PATH_32":"LD_LIBRARY_PATH_64"); -#endif - - newenvp = environ; - - { - char *newexec = execname; -#ifdef DUAL_MODE - /* - * If the data model is being changed, the path to the - * executable must be updated accordingly; the executable name - * and directory the executable resides in are separate. In the - * case of 32 => 64, the new bits are assumed to reside in, e.g. - * "olddir/BIGARCH/execname"; in the case of 64 => 32, - * the bits are assumed to be in "olddir/../execname". For example, - * - * olddir/sparcv9/execname - * olddir/amd64/execname - * - * for Solaris SPARC and Linux amd64, respectively. - */ - - if (running != wanted) { - char *oldexec = strcpy(MemAlloc(strlen(execname) + 1), execname); - char *olddir = oldexec; - char *oldbase = strrchr(oldexec, '/'); - - - newexec = MemAlloc(strlen(execname) + 20); - *oldbase++ = 0; - sprintf(newexec, "%s/%s/%s", olddir, - ((wanted==64) ? BIG_ARCH : ".."), oldbase); - argv[0] = newexec; - } -#endif - - execve(newexec, argv, newenvp); - perror("execve()"); - - fprintf(stderr, "Error trying to exec %s.\n", newexec); - fprintf(stderr, "Check if file exists and permissions are set correctly.\n"); - -#ifdef DUAL_MODE - if (running != wanted) { - fprintf(stderr, "Failed to start a %d-bit JVM process from a %d-bit JVM.\n", - wanted, running); -# ifdef __sun - -# ifdef __sparc - fprintf(stderr, "Verify all necessary J2SE components have been installed.\n" ); - fprintf(stderr, - "(Solaris SPARC 64-bit components must be installed after 32-bit components.)\n" ); -# else - fprintf(stderr, "Either 64-bit processes are not supported by this platform\n"); - fprintf(stderr, "or the 64-bit components have not been installed.\n"); -# endif - } -# endif -#endif - - } - - exit(1); - } - -#else /* ifndef GAMMA */ - - /* gamma launcher is simpler in that it doesn't handle VM flavors, data */ - /* model, LD_LIBRARY_PATH, etc. Assuming everything is set-up correctly */ - /* all we need to do here is to return correct path names. See also */ - /* GetJVMPath() and GetApplicationHome(). */ - - { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ - char *p; - - if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) { - fprintf(stderr, "Error: could not find Java 2 Runtime Environment.\n"); - exit(2); - } - - if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath, arch )) { - fprintf(stderr, "Error: no JVM at `%s'.\n", jvmpath); - exit(4); - } - } - -#endif /* ifndef GAMMA */ -} - - -/* - * On Solaris VM choosing is done by the launcher (java.c). - */ -static jboolean -GetJVMPath(const char *jrepath, const char *jvmtype, - char *jvmpath, jint jvmpathsize, char * arch) -{ - struct stat s; - -#ifndef GAMMA - if (strchr(jvmtype, '/')) { - sprintf(jvmpath, "%s/" JVM_DLL, jvmtype); - } else { - sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); - } -#else - /* For gamma launcher, JVM is either built-in or in the same directory. */ - /* Either way we return "/libjvm.so" where is the */ - /* directory where gamma launcher is located. */ - - char *p; - - snprintf(jvmpath, jvmpathsize, "%s", GetExecname()); - p = strrchr(jvmpath, '/'); - if (p) { - /* replace executable name with libjvm.so */ - snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL); - } else { - /* this case shouldn't happen */ - snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); - } -#endif - - if (_launcher_debug) - printf("Does `%s' exist ... ", jvmpath); - - if (stat(jvmpath, &s) == 0) { - if (_launcher_debug) - printf("yes.\n"); - return JNI_TRUE; - } else { - if (_launcher_debug) - printf("no.\n"); - return JNI_FALSE; - } -} - -/* - * Find path to JRE based on .exe's location or registry settings. - */ -static jboolean -GetJREPath(char *path, jint pathsize, char * arch, jboolean speculative) -{ - char libjava[MAXPATHLEN]; - - if (GetApplicationHome(path, pathsize)) { - /* Is JRE co-located with the application? */ - sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch); - if (access(libjava, F_OK) == 0) { - goto found; - } - - /* Does the app ship a private JRE in /jre directory? */ - sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch); - if (access(libjava, F_OK) == 0) { - strcat(path, "/jre"); - goto found; - } - } - - if (!speculative) - fprintf(stderr, "Error: could not find " JAVA_DLL "\n"); - return JNI_FALSE; - - found: - if (_launcher_debug) - printf("JRE path is %s\n", path); - return JNI_TRUE; -} - -jboolean -LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) -{ -#ifdef GAMMA - /* JVM is directly linked with gamma launcher; no dlopen() */ - ifn->CreateJavaVM = JNI_CreateJavaVM; - ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; - return JNI_TRUE; -#else - Dl_info dlinfo; - void *libjvm; - - if (_launcher_debug) { - printf("JVM path is %s\n", jvmpath); - } - - libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); - if (libjvm == NULL) { -#if defined(__sparc) && !defined(_LP64) /* i.e. 32-bit sparc */ - FILE * fp; - Elf32_Ehdr elf_head; - int count; - int location; - - fp = fopen(jvmpath, "r"); - if(fp == NULL) - goto error; - - /* read in elf header */ - count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp); - fclose(fp); - if(count < 1) - goto error; - - /* - * Check for running a server vm (compiled with -xarch=v8plus) - * on a stock v8 processor. In this case, the machine type in - * the elf header would not be included the architecture list - * provided by the isalist command, which is turn is gotten from - * sysinfo. This case cannot occur on 64-bit hardware and thus - * does not have to be checked for in binaries with an LP64 data - * model. - */ - if(elf_head.e_machine == EM_SPARC32PLUS) { - char buf[257]; /* recommended buffer size from sysinfo man - page */ - long length; - char* location; - - length = sysinfo(SI_ISALIST, buf, 257); - if(length > 0) { - location = strstr(buf, "sparcv8plus "); - if(location == NULL) { - fprintf(stderr, "SPARC V8 processor detected; Server compiler requires V9 or better.\n"); - fprintf(stderr, "Use Client compiler on V8 processors.\n"); - fprintf(stderr, "Could not create the Java virtual machine.\n"); - return JNI_FALSE; - } - } - } -#endif - fprintf(stderr, "dl failure on line %d", __LINE__); - goto error; - } - - ifn->CreateJavaVM = (CreateJavaVM_t) - dlsym(libjvm, "JNI_CreateJavaVM"); - if (ifn->CreateJavaVM == NULL) - goto error; - - ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) - dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); - if (ifn->GetDefaultJavaVMInitArgs == NULL) - goto error; - - return JNI_TRUE; - -error: - fprintf(stderr, "Error: failed %s, because %s\n", jvmpath, dlerror()); - return JNI_FALSE; -#endif /* GAMMA */ -} - -/* - * Get the path to the file that has the usage message for -X options. - */ -void -GetXUsagePath(char *buf, jint bufsize) -{ - static const char Xusage_txt[] = "/Xusage.txt"; - Dl_info dlinfo; - - /* we use RTLD_NOW because of problems with ld.so.1 and green threads */ - dladdr(dlsym(dlopen(JVM_DLL, RTLD_NOW), "JNI_CreateJavaVM"), &dlinfo); - strncpy(buf, (char *)dlinfo.dli_fname, bufsize - sizeof(Xusage_txt)); - - buf[bufsize-1] = '\0'; - strcpy(strrchr(buf, '/'), Xusage_txt); -} - -/* - * If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put - * "/foo" into buf. - */ -jboolean -GetApplicationHome(char *buf, jint bufsize) -{ -#ifdef __linux__ - char *execname = GetExecname(); - if (execname) { - strncpy(buf, execname, bufsize-1); - buf[bufsize-1] = '\0'; - } else { - return JNI_FALSE; - } -#else - Dl_info dlinfo; - - dladdr((void *)GetApplicationHome, &dlinfo); - if (realpath(dlinfo.dli_fname, buf) == NULL) { - fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname); - return JNI_FALSE; - } -#endif - -#ifdef GAMMA - { - /* gamma launcher uses JAVA_HOME environment variable to find JDK/JRE */ - char* java_home_var = getenv("JAVA_HOME"); - if (java_home_var == NULL) { - printf("JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); - return JNI_FALSE; - } - snprintf(buf, bufsize, "%s", java_home_var); - } -#else - if (strrchr(buf, '/') == 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - *(strrchr(buf, '/')) = '\0'; /* executable file */ - if (strlen(buf) < 4 || strrchr(buf, '/') == 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - if (strcmp("/bin", buf + strlen(buf) - 4) != 0) - *(strrchr(buf, '/')) = '\0'; /* sparcv9 or amd64 */ - if (strlen(buf) < 4 || strcmp("/bin", buf + strlen(buf) - 4) != 0) { - buf[0] = '\0'; - return JNI_FALSE; - } - *(strrchr(buf, '/')) = '\0'; /* bin */ -#endif /* GAMMA */ - - return JNI_TRUE; -} - - -/* - * Return true if the named program exists - */ -static int -ProgramExists(char *name) -{ - struct stat sb; - if (stat(name, &sb) != 0) return 0; - if (S_ISDIR(sb.st_mode)) return 0; - return (sb.st_mode & S_IEXEC) != 0; -} - - -/* - * Find a command in a directory, returning the path. - */ -static char * -Resolve(char *indir, char *cmd) -{ - char name[PATH_MAX + 2], *real; - - if ((strlen(indir) + strlen(cmd) + 1) > PATH_MAX) return 0; - sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd); - if (!ProgramExists(name)) return 0; - real = MemAlloc(PATH_MAX + 2); - if (!realpath(name, real)) - strcpy(real, name); - return real; -} - - -/* - * Find a path for the executable - */ -static char * -FindExecName(char *program) -{ - char cwdbuf[PATH_MAX+2]; - char *path; - char *tmp_path; - char *f; - char *result = NULL; - - /* absolute path? */ - if (*program == FILE_SEPARATOR || - (FILE_SEPARATOR=='\\' && strrchr(program, ':'))) - return Resolve("", program+1); - - /* relative path? */ - if (strrchr(program, FILE_SEPARATOR) != 0) { - char buf[PATH_MAX+2]; - return Resolve(getcwd(cwdbuf, sizeof(cwdbuf)), program); - } - - /* from search path? */ - path = getenv("PATH"); - if (!path || !*path) path = "."; - tmp_path = MemAlloc(strlen(path) + 2); - strcpy(tmp_path, path); - - for (f=tmp_path; *f && result==0; ) { - char *s = f; - while (*f && (*f != PATH_SEPARATOR)) ++f; - if (*f) *f++ = 0; - if (*s == FILE_SEPARATOR) - result = Resolve(s, program); - else { - /* relative path element */ - char dir[2*PATH_MAX]; - sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), - FILE_SEPARATOR, s); - result = Resolve(dir, program); - } - if (result != 0) break; - } - - free(tmp_path); - return result; -} - - -/* Store the name of the executable once computed */ -static char *execname = NULL; - -/* - * Compute the name of the executable - * - * In order to re-exec securely we need the absolute path of the - * executable. On Solaris getexecname(3c) may not return an absolute - * path so we use dladdr to get the filename of the executable and - * then use realpath to derive an absolute path. From Solaris 9 - * onwards the filename returned in DL_info structure from dladdr is - * an absolute pathname so technically realpath isn't required. - * On Linux we read the executable name from /proc/self/exe. - * As a fallback, and for platforms other than Solaris and Linux, - * we use FindExecName to compute the executable name. - */ -static char * -SetExecname(char **argv) -{ - char* exec_path = NULL; - - if (execname != NULL) /* Already determined */ - return (execname); - -#if defined(__sun) - { - Dl_info dlinfo; - if (dladdr((void*)&SetExecname, &dlinfo)) { - char *resolved = (char*)MemAlloc(PATH_MAX+1); - if (resolved != NULL) { - exec_path = realpath(dlinfo.dli_fname, resolved); - if (exec_path == NULL) { - free(resolved); - } - } - } - } -#elif defined(__linux__) - { - const char* self = "/proc/self/exe"; - char buf[PATH_MAX+1]; - int len = readlink(self, buf, PATH_MAX); - if (len >= 0) { - buf[len] = '\0'; /* readlink doesn't nul terminate */ - exec_path = strdup(buf); - } - } -#else /* !__sun && !__linux */ - { - /* Not implemented */ - } -#endif - - if (exec_path == NULL) { - exec_path = FindExecName(argv[0]); - } - execname = exec_path; - return exec_path; -} - -/* - * Return the name of the executable. Used in java_md.c to find the JRE area. - */ -static char * -GetExecname() { - return execname; -} - -void ReportErrorMessage(char * message, jboolean always) { - if (always) { - fprintf(stderr, "%s\n", message); - } -} - -void ReportErrorMessage2(char * format, char * string, jboolean always) { - if (always) { - fprintf(stderr, format, string); - fprintf(stderr, "\n"); - } -} - -void ReportExceptionDescription(JNIEnv * env) { - (*env)->ExceptionDescribe(env); -} - -/* - * Return JNI_TRUE for an option string that has no effect but should - * _not_ be passed on to the vm; return JNI_FALSE otherwise. On - * Solaris SPARC, this screening needs to be done if: - * 1) LD_LIBRARY_PATH does _not_ need to be reset and - * 2) -d32 or -d64 is passed to a binary with a matching data model - * (the exec in SetLibraryPath removes -d options and points the - * exec to the proper binary). When this exec is not done, these options - * would end up getting passed onto the vm. - */ -jboolean RemovableMachineDependentOption(char * option) { - /* - * Unconditionally remove both -d32 and -d64 options since only - * the last such options has an effect; e.g. - * java -d32 -d64 -d32 -version - * is equivalent to - * java -d32 -version - */ - - if( (strcmp(option, "-d32") == 0 ) || - (strcmp(option, "-d64") == 0 )) - return JNI_TRUE; - else - return JNI_FALSE; -} - -void PrintMachineDependentOptions() { - fprintf(stdout, - " -d32 use a 32-bit data model if available\n" - "\n" - " -d64 use a 64-bit data model if available\n"); - return; -} - -#ifndef GAMMA /* gamma launcher does not have ergonomics */ - -/* - * The following methods (down to ServerClassMachine()) answer - * the question about whether a machine is a "server-class" - * machine. A server-class machine is loosely defined as one - * with 2 or more processors and 2 gigabytes or more physical - * memory. The definition of a processor is a physical package, - * not a hyperthreaded chip masquerading as a multi-processor. - * The definition of memory is also somewhat fuzzy, since x86 - * machines seem not to report all the memory in their DIMMs, we - * think because of memory mapping of graphics cards, etc. - * - * This code is somewhat more confused with #ifdef's than we'd - * like because this file is used by both Solaris and Linux - * platforms, and so needs to be parameterized for SPARC and - * i586 hardware. The other Linux platforms (amd64 and ia64) - * don't even ask this question, because they only come with - * server JVMs. */ - -# define KB (1024UL) -# define MB (1024UL * KB) -# define GB (1024UL * MB) - -/* Compute physical memory by asking the OS */ -uint64_t -physical_memory(void) { - const uint64_t pages = (uint64_t) sysconf(_SC_PHYS_PAGES); - const uint64_t page_size = (uint64_t) sysconf(_SC_PAGESIZE); - const uint64_t result = pages * page_size; -# define UINT64_FORMAT "%" PRIu64 - - if (_launcher_debug) { - printf("pages: " UINT64_FORMAT - " page_size: " UINT64_FORMAT - " physical memory: " UINT64_FORMAT " (%.3fGB)\n", - pages, page_size, result, result / (double) GB); - } - return result; -} - -#if defined(__sun) && defined(__sparc) - -/* Methods for solaris-sparc: these are easy. */ - -/* Ask the OS how many processors there are. */ -unsigned long -physical_processors(void) { - const unsigned long sys_processors = sysconf(_SC_NPROCESSORS_CONF); - - if (_launcher_debug) { - printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); - } - return sys_processors; -} - -/* The solaris-sparc version of the "server-class" predicate. */ -jboolean -solaris_sparc_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= server_memory) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("solaris_" ARCH "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "JNI_TRUE" : "JNI_FALSE")); - } - return result; -} - -#endif /* __sun && __sparc */ - -#if defined(__sun) && defined(i586) - -/* - * A utility method for asking the CPU about itself. - * There's a corresponding version of linux-i586 - * because the compilers are different. - */ -void -get_cpuid(uint32_t arg, - uint32_t* eaxp, - uint32_t* ebxp, - uint32_t* ecxp, - uint32_t* edxp) { -#ifdef _LP64 - asm( - /* rbx is a callee-saved register */ - " movq %rbx, %r11 \n" - /* rdx and rcx are 3rd and 4th argument registers */ - " movq %rdx, %r10 \n" - " movq %rcx, %r9 \n" - " movl %edi, %eax \n" - " cpuid \n" - " movl %eax, (%rsi)\n" - " movl %ebx, (%r10)\n" - " movl %ecx, (%r9) \n" - " movl %edx, (%r8) \n" - /* Restore rbx */ - " movq %r11, %rbx"); -#else - /* EBX is a callee-saved register */ - asm(" pushl %ebx"); - /* Need ESI for storing through arguments */ - asm(" pushl %esi"); - asm(" movl 8(%ebp), %eax \n" - " cpuid \n" - " movl 12(%ebp), %esi \n" - " movl %eax, (%esi) \n" - " movl 16(%ebp), %esi \n" - " movl %ebx, (%esi) \n" - " movl 20(%ebp), %esi \n" - " movl %ecx, (%esi) \n" - " movl 24(%ebp), %esi \n" - " movl %edx, (%esi) "); - /* Restore ESI and EBX */ - asm(" popl %esi"); - /* Restore EBX */ - asm(" popl %ebx"); -#endif -} - -#endif /* __sun && i586 */ - -#if defined(__linux__) && defined(i586) - -/* - * A utility method for asking the CPU about itself. - * There's a corresponding version of solaris-i586 - * because the compilers are different. - */ -void -get_cpuid(uint32_t arg, - uint32_t* eaxp, - uint32_t* ebxp, - uint32_t* ecxp, - uint32_t* edxp) { -#ifdef _LP64 - __asm__ volatile (/* Instructions */ - " movl %4, %%eax \n" - " cpuid \n" - " movl %%eax, (%0)\n" - " movl %%ebx, (%1)\n" - " movl %%ecx, (%2)\n" - " movl %%edx, (%3)\n" - : /* Outputs */ - : /* Inputs */ - "r" (eaxp), - "r" (ebxp), - "r" (ecxp), - "r" (edxp), - "r" (arg) - : /* Clobbers */ - "%rax", "%rbx", "%rcx", "%rdx", "memory" - ); -#else - uint32_t value_of_eax = 0; - uint32_t value_of_ebx = 0; - uint32_t value_of_ecx = 0; - uint32_t value_of_edx = 0; - __asm__ volatile (/* Instructions */ - /* ebx is callee-save, so push it */ - /* even though it's in the clobbers section */ - " pushl %%ebx \n" - " movl %4, %%eax \n" - " cpuid \n" - " movl %%eax, %0 \n" - " movl %%ebx, %1 \n" - " movl %%ecx, %2 \n" - " movl %%edx, %3 \n" - /* restore ebx */ - " popl %%ebx \n" - - : /* Outputs */ - "=m" (value_of_eax), - "=m" (value_of_ebx), - "=m" (value_of_ecx), - "=m" (value_of_edx) - : /* Inputs */ - "m" (arg) - : /* Clobbers */ - "%eax", "%ebx", "%ecx", "%edx" - ); - *eaxp = value_of_eax; - *ebxp = value_of_ebx; - *ecxp = value_of_ecx; - *edxp = value_of_edx; -#endif -} - -#endif /* __linux__ && i586 */ - -#ifdef i586 -/* - * Routines shared by solaris-i586 and linux-i586. - */ - -enum HyperThreadingSupport_enum { - hts_supported = 1, - hts_too_soon_to_tell = 0, - hts_not_supported = -1, - hts_not_pentium4 = -2, - hts_not_intel = -3 -}; -typedef enum HyperThreadingSupport_enum HyperThreadingSupport; - -/* Determine if hyperthreading is supported */ -HyperThreadingSupport -hyperthreading_support(void) { - HyperThreadingSupport result = hts_too_soon_to_tell; - /* Bits 11 through 8 is family processor id */ -# define FAMILY_ID_SHIFT 8 -# define FAMILY_ID_MASK 0xf - /* Bits 23 through 20 is extended family processor id */ -# define EXT_FAMILY_ID_SHIFT 20 -# define EXT_FAMILY_ID_MASK 0xf - /* Pentium 4 family processor id */ -# define PENTIUM4_FAMILY_ID 0xf - /* Bit 28 indicates Hyper-Threading Technology support */ -# define HT_BIT_SHIFT 28 -# define HT_BIT_MASK 1 - uint32_t vendor_id[3] = { 0U, 0U, 0U }; - uint32_t value_of_eax = 0U; - uint32_t value_of_edx = 0U; - uint32_t dummy = 0U; - - /* Yes, this is supposed to be [0], [2], [1] */ - get_cpuid(0, &dummy, &vendor_id[0], &vendor_id[2], &vendor_id[1]); - if (_launcher_debug) { - printf("vendor: %c %c %c %c %c %c %c %c %c %c %c %c \n", - ((vendor_id[0] >> 0) & 0xff), - ((vendor_id[0] >> 8) & 0xff), - ((vendor_id[0] >> 16) & 0xff), - ((vendor_id[0] >> 24) & 0xff), - ((vendor_id[1] >> 0) & 0xff), - ((vendor_id[1] >> 8) & 0xff), - ((vendor_id[1] >> 16) & 0xff), - ((vendor_id[1] >> 24) & 0xff), - ((vendor_id[2] >> 0) & 0xff), - ((vendor_id[2] >> 8) & 0xff), - ((vendor_id[2] >> 16) & 0xff), - ((vendor_id[2] >> 24) & 0xff)); - } - get_cpuid(1, &value_of_eax, &dummy, &dummy, &value_of_edx); - if (_launcher_debug) { - printf("value_of_eax: 0x%x value_of_edx: 0x%x\n", - value_of_eax, value_of_edx); - } - if ((((value_of_eax >> FAMILY_ID_SHIFT) & FAMILY_ID_MASK) == PENTIUM4_FAMILY_ID) || - (((value_of_eax >> EXT_FAMILY_ID_SHIFT) & EXT_FAMILY_ID_MASK) != 0)) { - if ((((vendor_id[0] >> 0) & 0xff) == 'G') && - (((vendor_id[0] >> 8) & 0xff) == 'e') && - (((vendor_id[0] >> 16) & 0xff) == 'n') && - (((vendor_id[0] >> 24) & 0xff) == 'u') && - (((vendor_id[1] >> 0) & 0xff) == 'i') && - (((vendor_id[1] >> 8) & 0xff) == 'n') && - (((vendor_id[1] >> 16) & 0xff) == 'e') && - (((vendor_id[1] >> 24) & 0xff) == 'I') && - (((vendor_id[2] >> 0) & 0xff) == 'n') && - (((vendor_id[2] >> 8) & 0xff) == 't') && - (((vendor_id[2] >> 16) & 0xff) == 'e') && - (((vendor_id[2] >> 24) & 0xff) == 'l')) { - if (((value_of_edx >> HT_BIT_SHIFT) & HT_BIT_MASK) == HT_BIT_MASK) { - if (_launcher_debug) { - printf("Hyperthreading supported\n"); - } - result = hts_supported; - } else { - if (_launcher_debug) { - printf("Hyperthreading not supported\n"); - } - result = hts_not_supported; - } - } else { - if (_launcher_debug) { - printf("Not GenuineIntel\n"); - } - result = hts_not_intel; - } - } else { - if (_launcher_debug) { - printf("not Pentium 4 or extended\n"); - } - result = hts_not_pentium4; - } - return result; -} - -/* Determine how many logical processors there are per CPU */ -unsigned int -logical_processors_per_package(void) { - /* - * After CPUID with EAX==1, register EBX bits 23 through 16 - * indicate the number of logical processors per package - */ -# define NUM_LOGICAL_SHIFT 16 -# define NUM_LOGICAL_MASK 0xff - unsigned int result = 1U; - const HyperThreadingSupport hyperthreading = hyperthreading_support(); - - if (hyperthreading == hts_supported) { - uint32_t value_of_ebx = 0U; - uint32_t dummy = 0U; - - get_cpuid(1, &dummy, &value_of_ebx, &dummy, &dummy); - result = (value_of_ebx >> NUM_LOGICAL_SHIFT) & NUM_LOGICAL_MASK; - if (_launcher_debug) { - printf("logical processors per package: %u\n", result); - } - } - return result; -} - -/* Compute the number of physical processors, not logical processors */ -unsigned long -physical_processors(void) { - const long sys_processors = sysconf(_SC_NPROCESSORS_CONF); - unsigned long result = sys_processors; - - if (_launcher_debug) { - printf("sysconf(_SC_NPROCESSORS_CONF): %lu\n", sys_processors); - } - if (sys_processors > 1) { - unsigned int logical_processors = logical_processors_per_package(); - if (logical_processors > 1) { - result = (unsigned long) sys_processors / logical_processors; - } - } - if (_launcher_debug) { - printf("physical processors: %lu\n", result); - } - return result; -} - -#endif /* i586 */ - -#if defined(__sun) && defined(i586) - -/* The definition of a server-class machine for solaris-i586/amd64 */ -jboolean -solaris_i586_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - /* - * We seem not to get our full complement of memory. - * We allow some part (1/8?) of the memory to be "missing", - * based on the sizes of DIMMs, and maybe graphics cards. - */ - const uint64_t missing_memory = 256UL * MB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= (server_memory - missing_memory)) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("solaris_" ARCH "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "true" : "false")); - } - return result; -} - -#endif /* __sun && i586 */ - -#if defined(__linux__) && defined(i586) - -/* The definition of a server-class machine for linux-i586 */ -jboolean -linux_i586_ServerClassMachine(void) { - jboolean result = JNI_FALSE; - /* How big is a server class machine? */ - const unsigned long server_processors = 2UL; - const uint64_t server_memory = 2UL * GB; - /* - * We seem not to get our full complement of memory. - * We allow some part (1/8?) of the memory to be "missing", - * based on the sizes of DIMMs, and maybe graphics cards. - */ - const uint64_t missing_memory = 256UL * MB; - const uint64_t actual_memory = physical_memory(); - - /* Is this a server class machine? */ - if (actual_memory >= (server_memory - missing_memory)) { - const unsigned long actual_processors = physical_processors(); - if (actual_processors >= server_processors) { - result = JNI_TRUE; - } - } - if (_launcher_debug) { - printf("linux_" ARCH "_ServerClassMachine: %s\n", - (result == JNI_TRUE ? "true" : "false")); - } - return result; -} - -#endif /* __linux__ && i586 */ - -/* Dispatch to the platform-specific definition of "server-class" */ -jboolean -ServerClassMachine(void) { - jboolean result = JNI_FALSE; -#if defined(__sun) && defined(__sparc) - result = solaris_sparc_ServerClassMachine(); -#elif defined(__sun) && defined(i586) - result = solaris_i586_ServerClassMachine(); -#elif defined(__linux__) && defined(i586) - result = linux_i586_ServerClassMachine(); -#else - if (_launcher_debug) { - printf("ServerClassMachine: returns default value of %s\n", - (result == JNI_TRUE ? "true" : "false")); - } -#endif - return result; -} - -#endif /* ifndef GAMMA */ - -#ifndef GAMMA /* gamma launcher does not choose JDK/JRE/JVM */ - -/* - * Since using the file system as a registry is a bit risky, perform - * additional sanity checks on the identified directory to validate - * it as a valid jre/sdk. - * - * Return 0 if the tests fail; otherwise return non-zero (true). - * - * Note that checking for anything more than the existence of an - * executable object at bin/java relative to the path being checked - * will break the regression tests. - */ -static int -CheckSanity(char *path, char *dir) -{ - char buffer[PATH_MAX]; - - if (strlen(path) + strlen(dir) + 11 > PATH_MAX) - return (0); /* Silently reject "impossibly" long paths */ - - (void)strcat(strcat(strcat(strcpy(buffer, path), "/"), dir), "/bin/java"); - return ((access(buffer, X_OK) == 0) ? 1 : 0); -} - -/* - * Determine if there is an acceptable JRE in the directory dirname. - * Upon locating the "best" one, return a fully qualified path to - * it. "Best" is defined as the most advanced JRE meeting the - * constraints contained in the manifest_info. If no JRE in this - * directory meets the constraints, return NULL. - * - * Note that we don't check for errors in reading the directory - * (which would be done by checking errno). This is because it - * doesn't matter if we get an error reading the directory, or - * we just don't find anything interesting in the directory. We - * just return NULL in either case. - * - * The historical names of j2sdk and j2re were changed to jdk and - * jre respecively as part of the 1.5 rebranding effort. Since the - * former names are legacy on Linux, they must be recognized for - * all time. Fortunately, this is a minor cost. - */ -static char -*ProcessDir(manifest_info *info, char *dirname) -{ - DIR *dirp; - struct dirent *dp; - char *best = NULL; - int offset; - int best_offset = 0; - char *ret_str = NULL; - char buffer[PATH_MAX]; - - if ((dirp = opendir(dirname)) == NULL) - return (NULL); - - do { - if ((dp = readdir(dirp)) != NULL) { - offset = 0; - if ((strncmp(dp->d_name, "jre", 3) == 0) || - (strncmp(dp->d_name, "jdk", 3) == 0)) - offset = 3; - else if (strncmp(dp->d_name, "j2re", 4) == 0) - offset = 4; - else if (strncmp(dp->d_name, "j2sdk", 5) == 0) - offset = 5; - if (offset > 0) { - if ((acceptable_release(dp->d_name + offset, - info->jre_version)) && CheckSanity(dirname, dp->d_name)) - if ((best == NULL) || (exact_version_id( - dp->d_name + offset, best + best_offset) > 0)) { - if (best != NULL) - free(best); - best = strdup(dp->d_name); - best_offset = offset; - } - } - } - } while (dp != NULL); - (void) closedir(dirp); - if (best == NULL) - return (NULL); - else { - ret_str = MemAlloc(strlen(dirname) + strlen(best) + 2); - ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best); - free(best); - return (ret_str); - } -} - -/* - * This is the global entry point. It examines the host for the optimal - * JRE to be used by scanning a set of directories. The set of directories - * is platform dependent and can be overridden by the environment - * variable JAVA_VERSION_PATH. - * - * This routine itself simply determines the set of appropriate - * directories before passing control onto ProcessDir(). - */ -char* -LocateJRE(manifest_info* info) -{ - char *path; - char *home; - char *target = NULL; - char *dp; - char *cp; - - /* - * Start by getting JAVA_VERSION_PATH - */ - if (info->jre_restrict_search) - path = strdup(system_dir); - else if ((path = getenv("JAVA_VERSION_PATH")) != NULL) - path = strdup(path); - else - if ((home = getenv("HOME")) != NULL) { - path = (char *)MemAlloc(strlen(home) + 13); - path = strcat(strcat(strcat(strcpy(path, home), - user_dir), ":"), system_dir); - } else - path = strdup(system_dir); - - /* - * Step through each directory on the path. Terminate the scan with - * the first directory with an acceptable JRE. - */ - cp = dp = path; - while (dp != NULL) { - cp = strchr(dp, (int)':'); - if (cp != NULL) - *cp = (char)NULL; - if ((target = ProcessDir(info, dp)) != NULL) - break; - dp = cp; - if (dp != NULL) - dp++; - } - free(path); - return (target); -} - -/* - * Given a path to a jre to execute, this routine checks if this process - * is indeed that jre. If not, it exec's that jre. - * - * We want to actually check the paths rather than just the version string - * built into the executable, so that given version specification (and - * JAVA_VERSION_PATH) will yield the exact same Java environment, regardless - * of the version of the arbitrary launcher we start with. - */ -void -ExecJRE(char *jre, char **argv) -{ - char wanted[PATH_MAX]; - char *execname; - char *progname; - - /* - * Resolve the real path to the directory containing the selected JRE. - */ - if (realpath(jre, wanted) == NULL) { - fprintf(stderr, "Unable to resolve %s\n", jre); - exit(1); - } - - /* - * Resolve the real path to the currently running launcher. - */ - execname = SetExecname(argv); - if (execname == NULL) { - fprintf(stderr, "Unable to resolve current executable\n"); - exit(1); - } - - /* - * If the path to the selected JRE directory is a match to the initial - * portion of the path to the currently executing JRE, we have a winner! - * If so, just return. - */ - if (strncmp(wanted, execname, strlen(wanted)) == 0) - return; /* I am the droid you were looking for */ - - /* - * If this isn't the selected version, exec the selected version. - */ -#ifdef JAVA_ARGS /* javac, jar and friends. */ - progname = "java"; -#else /* java, oldjava, javaw and friends */ -#ifdef PROGNAME - progname = PROGNAME; -#else - progname = *argv; - if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { - progname = s + 1; - } -#endif /* PROGNAME */ -#endif /* JAVA_ARGS */ - - /* - * This should never happen (because of the selection code in SelectJRE), - * but check for "impossibly" long path names just because buffer overruns - * can be so deadly. - */ - if (strlen(wanted) + strlen(progname) + 6 > PATH_MAX) { - fprintf(stderr, "Path length exceeds maximum length (PATH_MAX)\n"); - exit(1); - } - - /* - * Construct the path and exec it. - */ - (void)strcat(strcat(wanted, "/bin/"), progname); - argv[0] = progname; - if (_launcher_debug) { - int i; - printf("execv(\"%s\"", wanted); - for (i = 0; argv[i] != NULL; i++) - printf(", \"%s\"", argv[i]); - printf(")\n"); - } - execv(wanted, argv); - fprintf(stderr, "Exec of %s failed\n", wanted); - exit(1); -} - -#endif /* ifndef GAMMA */ - -/* - * "Borrowed" from Solaris 10 where the unsetenv() function is being added - * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As - * such, in the fullness of time this will appear in libc on all relevant - * Solaris/Linux platforms and maybe even the Windows platform. At that - * time, this stub can be removed. - * - * This implementation removes the environment locking for multithreaded - * applications. (We don't have access to these mutexes within libc and - * the launcher isn't multithreaded.) Note that what remains is platform - * independent, because it only relies on attributes that a POSIX environment - * defines. - * - * Returns 0 on success, -1 on failure. - * - * Also removed was the setting of errno. The only value of errno set - * was EINVAL ("Invalid Argument"). - */ - -/* - * s1(environ) is name=value - * s2(name) is name(not the form of name=value). - * if names match, return value of 1, else return 0 - */ -static int -match_noeq(const char *s1, const char *s2) -{ - while (*s1 == *s2++) { - if (*s1++ == '=') - return (1); - } - if (*s1 == '=' && s2[-1] == '\0') - return (1); - return (0); -} - -/* - * added for SUSv3 standard - * - * Delete entry from environ. - * Do not free() memory! Other threads may be using it. - * Keep it around forever. - */ -static int -borrowed_unsetenv(const char *name) -{ - long idx; /* index into environ */ - - if (name == NULL || *name == '\0' || - strchr(name, '=') != NULL) { - return (-1); - } - - for (idx = 0; environ[idx] != NULL; idx++) { - if (match_noeq(environ[idx], name)) - break; - } - if (environ[idx] == NULL) { - /* name not found but still a success */ - return (0); - } - /* squeeze up one entry */ - do { - environ[idx] = environ[idx+1]; - } while (environ[++idx] != NULL); - - return (0); -} -/* --- End of "borrowed" code --- */ - -/* - * Wrapper for unsetenv() function. - */ -int -UnsetEnv(char *name) -{ - return(borrowed_unsetenv(name)); -} - -/* - * The implementation for finding classes from the bootstrap - * class loader, refer to java.h - */ -static FindClassFromBootLoader_t *findBootClass = NULL; - -jclass -FindBootStrapClass(JNIEnv *env, const char* classname) -{ - if (findBootClass == NULL) { - findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT, - "JVM_FindClassFromBootLoader"); - if (findBootClass == NULL) { - fprintf(stderr, "Error: could not load method JVM_FindClassFromBootLoader"); - return NULL; - } - } - return findBootClass(env, classname, JNI_FALSE); -} - diff --git a/src/os/solaris/vm/hpi_solaris.cpp b/src/os/solaris/vm/hpi_solaris.cpp deleted file mode 100644 index a3a500e2de3c536e491d9b3f7ad408e503ae0ade..0000000000000000000000000000000000000000 --- a/src/os/solaris/vm/hpi_solaris.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/hpi.hpp" -#include "runtime/os.hpp" - -# include -# include - -typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *); - -void hpi::initialize_get_interface(vm_calls_t *callbacks) -{ - char buf[JVM_MAXPATHLEN]; - void *hpi_handle; - GetInterfaceFunc& getintf = _get_interface; - jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *); - - if (HPILibPath && HPILibPath[0]) { - strncpy(buf, HPILibPath, JVM_MAXPATHLEN - 1); - buf[JVM_MAXPATHLEN - 1] = '\0'; - } else { - const char *thread_type = "native_threads"; - - os::jvm_path(buf, JVM_MAXPATHLEN); - -#ifdef PRODUCT - const char * hpi_lib = "/libhpi.so"; -#else - char * ptr = strrchr(buf, '/'); - assert(strstr(ptr, "/libjvm") == ptr, "invalid library name"); - const char * hpi_lib = strstr(ptr, "_g") ? "/libhpi_g.so" : "/libhpi.so"; -#endif - - *(strrchr(buf, '/')) = '\0'; /* get rid of /libjvm.so */ - char* p = strrchr(buf, '/'); - if (p != NULL) p[1] = '\0'; /* get rid of hotspot */ - strcat(buf, thread_type); - strcat(buf, hpi_lib); - } - /* we use RTLD_NOW because of bug 4032715 */ - if (TraceHPI) tty->print_cr("Loading HPI %s ", buf); - hpi_handle = dlopen(buf, RTLD_NOW); - if (hpi_handle == NULL) { - if (TraceHPI) tty->print_cr("HPI dlopen failed: %s", dlerror()); - return; - } - DLL_Initialize = CAST_TO_FN_PTR(jint (JNICALL *)(GetInterfaceFunc *, void *), - dlsym(hpi_handle, "DLL_Initialize")); - if (TraceHPI && DLL_Initialize == NULL) tty->print_cr("HPI dlsym of DLL_Initialize failed: %s", dlerror()); - if (DLL_Initialize == NULL || - (*DLL_Initialize)(&getintf, callbacks) < 0) { - if (TraceHPI) tty->print_cr("HPI DLL_Initialize failed"); - return; - } - if (TraceHPI) tty->print_cr("HPI loaded successfully"); -} diff --git a/src/os/solaris/vm/hpi_solaris.hpp b/src/os/solaris/vm/hpi_solaris.hpp deleted file mode 100644 index 27173fd5a8d5367231bae8c5c884cb09116216a8..0000000000000000000000000000000000000000 --- a/src/os/solaris/vm/hpi_solaris.hpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 OS_SOLARIS_VM_HPI_SOLARIS_HPP -#define OS_SOLARIS_VM_HPI_SOLARIS_HPP - -// -// Parts of the HPI interface for which the HotSparc does not use the -// HPI (because the interruptible IO mechanims used are different). -// - -#include -#include -#include -#include -#include -#include - -// HPI_FileInterface - -// Many system calls can be interrupted by signals and must be restarted. -// Restart support was added without disturbing the extent of thread -// interruption support. - -inline int hpi::close(int fd) { - RESTARTABLE_RETURN_INT(::close(fd)); -} - -inline size_t hpi::read(int fd, void *buf, unsigned int nBytes) { - INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); -} - -inline size_t hpi::write(int fd, const void *buf, unsigned int nBytes) { - INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted); -} - - -// HPI_SocketInterface - -inline int hpi::socket_close(int fd) { - RESTARTABLE_RETURN_INT(::close(fd)); -} - -inline int hpi::socket(int domain, int type, int protocol) { - return ::socket(domain, type, protocol); -} - -inline int hpi::recv(int fd, char *buf, int nBytes, int flags) { - INTERRUPTIBLE_RETURN_INT(::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); -} - -inline int hpi::send(int fd, char *buf, int nBytes, int flags) { - INTERRUPTIBLE_RETURN_INT(::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); -} - -inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) { - RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags)); -} - -// As both poll and select can be interrupted by signals, we have to be -// prepared to restart the system call after updating the timeout, unless -// a poll() is done with timeout == -1, in which case we repeat with this -// "wait forever" value. - -inline int hpi::timeout(int fd, long timeout) { - int res; - struct timeval t; - julong prevtime, newtime; - static const char* aNull = 0; - - struct pollfd pfd; - pfd.fd = fd; - pfd.events = POLLIN; - - gettimeofday(&t, &aNull); - prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; - - for(;;) { - INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted); - if(res == OS_ERR && errno == EINTR) { - if(timeout != -1) { - gettimeofday(&t, &aNull); - newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000; - timeout -= newtime - prevtime; - if(timeout <= 0) - return OS_OK; - prevtime = newtime; - } - } else - return res; - } -} - -inline int hpi::listen(int fd, int count) { - if (fd < 0) - return OS_ERR; - - return ::listen(fd, count); -} - -inline int -hpi::connect(int fd, struct sockaddr *him, int len) { - do { - int _result; - INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result, - os::Solaris::clear_interrupted); - - // Depending on when thread interruption is reset, _result could be - // one of two values when errno == EINTR - - if (((_result == OS_INTRPT) || (_result == OS_ERR)) && (errno == EINTR)) { - /* restarting a connect() changes its errno semantics */ - INTERRUPTIBLE(::connect(fd, him, len), _result, - os::Solaris::clear_interrupted); - /* undo these changes */ - if (_result == OS_ERR) { - if (errno == EALREADY) errno = EINPROGRESS; /* fall through */ - else if (errno == EISCONN) { errno = 0; return OS_OK; } - } - } - return _result; - } while(false); -} - -inline int hpi::accept(int fd, struct sockaddr *him, int *len) { - if (fd < 0) - return OS_ERR; - INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him, (socklen_t*) len), os::Solaris::clear_interrupted); -} - -inline int hpi::recvfrom(int fd, char *buf, int nBytes, int flags, - sockaddr *from, int *fromlen) { - //%%note jvm_r11 - INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes, (unsigned int) flags, from, (socklen_t *)fromlen), os::Solaris::clear_interrupted); -} - -inline int hpi::sendto(int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen) { - //%%note jvm_r11 - INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, (unsigned int) flags, to, tolen),os::Solaris::clear_interrupted); -} - -inline int hpi::socket_available(int fd, jint *pbytes) { - if (fd < 0) - return OS_OK; - - int ret; - - RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); - - //%% note ioctl can return 0 when successful, JVM_SocketAvailable - // is expected to return 0 on failure and 1 on success to the jdk. - - return (ret == OS_ERR) ? 0 : 1; -} - - -/* -HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown, - int, "%d", - (int fd, int howto), - ("fd = %d, howto = %d", fd, howto), - (fd, howto)); - */ -inline int hpi::socket_shutdown(int fd, int howto){ - return ::shutdown(fd, howto); -} - -/* -HPIDECL(bind, "bind", _socket, Bind, - int, "%d", - (int fd, struct sockaddr *him, int len), - ("fd = %d, him = %p, len = %d", - fd, him, len), - (fd, him, len)); -*/ -inline int hpi::bind(int fd, struct sockaddr *him, int len){ - INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),os::Solaris::clear_interrupted); -} - -/* -HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName, - int, "%d", - (int fd, struct sockaddr *him, int *len), - ("fd = %d, him = %p, len = %p", - fd, him, len), - (fd, him, len)); - */ -inline int hpi::get_sock_name(int fd, struct sockaddr *him, int *len){ - return ::getsockname(fd, him, (socklen_t*) len); -} - -/* -HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d", - (char *hostname, int namelen), - ("hostname = %p, namelen = %d", - hostname, namelen), - (hostname, namelen)); - */ -inline int hpi::get_host_name(char* name, int namelen){ - return ::gethostname(name, namelen); -} - -/* -HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d", - (int fd, int level, int optname, char *optval, int* optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - */ -inline int hpi::get_sock_opt(int fd, int level, int optname, - char *optval, int* optlen){ - return ::getsockopt(fd, level, optname, optval, (socklen_t*) optlen); -} - -/* -HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d", - (int fd, int level, int optname, const char *optval, int optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - */ -inline int hpi::set_sock_opt(int fd, int level, int optname, - const char *optval, int optlen){ - return ::setsockopt(fd, level, optname, optval, optlen); -} - -//Reconciliation History -// 1.3 98/10/21 18:17:14 hpi_win32.hpp -// 1.6 99/06/28 11:01:36 hpi_win32.hpp -//End - -#endif // OS_SOLARIS_VM_HPI_SOLARIS_HPP diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp index c88fb0d5803c70225d1e74968b3e39462e001788..f9898d33246614d678e7254d392e2e39759f89ea 100644 --- a/src/os/solaris/vm/os_solaris.cpp +++ b/src/os/solaris/vm/os_solaris.cpp @@ -42,7 +42,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -115,6 +114,7 @@ # include # include # include +# include # define _STRUCTURED_PROC 1 // this gets us the new structured proc interfaces of 5.6 & later # include // see comment in @@ -219,6 +219,9 @@ int prio_policy1[MaxPriority+1] = { -99999, 0, 16, 32, 48, 64, // System parameters used internally static clock_t clock_tics_per_sec = 100; +// Track if we have called enable_extended_FILE_stdio (on Solaris 10u4+) +static bool enabled_extended_FILE_stdio = false; + // For diagnostics to print a message once. see run_periodic_checks static bool check_addr0_done = false; static sigset_t check_signal_done; @@ -386,7 +389,7 @@ struct tm* os::localtime_pd(const time_t* clock, struct tm* res) { // The saved state is used to restore the thread to // its former state whether or not an interrupt is received. // Used by classloader os::read -// hpi calls skip this layer and stay in _thread_in_native +// os::restartable_read calls skip this layer and stay in _thread_in_native void os::Solaris::setup_interruptible(JavaThread* thread) { @@ -1750,13 +1753,13 @@ bool os::getTimesSecs(double* process_real_time, bool os::supports_vtime() { return true; } bool os::enable_vtime() { - int fd = open("/proc/self/ctl", O_WRONLY); + int fd = ::open("/proc/self/ctl", O_WRONLY); if (fd == -1) return false; long cmd[] = { PCSET, PR_MSACCT }; - int res = write(fd, cmd, sizeof(long) * 2); - close(fd); + int res = ::write(fd, cmd, sizeof(long) * 2); + ::close(fd); if (res != sizeof(long) * 2) return false; @@ -1764,13 +1767,13 @@ bool os::enable_vtime() { } bool os::vtime_enabled() { - int fd = open("/proc/self/status", O_RDONLY); + int fd = ::open("/proc/self/status", O_RDONLY); if (fd == -1) return false; pstatus_t status; - int res = read(fd, (void*) &status, sizeof(pstatus_t)); - close(fd); + int res = os::read(fd, (void*) &status, sizeof(pstatus_t)); + ::close(fd); if (res != sizeof(pstatus_t)) return false; @@ -1886,7 +1889,6 @@ static bool file_exists(const char* filename) { void os::dll_build_name(char* buffer, size_t buflen, const char* pname, const char* fname) { - // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; // Quietly truncate on buffer overflow. Should be an error. @@ -2182,20 +2184,29 @@ void* os::dll_lookup(void* handle, const char* name) { return dlsym(handle, name); } +int os::stat(const char *path, struct stat *sbuf) { + char pathbuf[MAX_PATH]; + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::stat(pathbuf, sbuf); +} -bool _print_ascii_file(const char* filename, outputStream* st) { - int fd = open(filename, O_RDONLY); +static bool _print_ascii_file(const char* filename, outputStream* st) { + int fd = ::open(filename, O_RDONLY); if (fd == -1) { return false; } char buf[32]; int bytes; - while ((bytes = read(fd, buf, sizeof(buf))) > 0) { + while ((bytes = ::read(fd, buf, sizeof(buf))) > 0) { st->print_raw(buf, bytes); } - close(fd); + ::close(fd); return true; } @@ -2258,10 +2269,10 @@ void os::print_os_info(outputStream* st) { static bool check_addr0(outputStream* st) { jboolean status = false; - int fd = open("/proc/self/map",O_RDONLY); + int fd = ::open("/proc/self/map",O_RDONLY); if (fd >= 0) { prmap_t p; - while(read(fd, &p, sizeof(p)) > 0) { + while(::read(fd, &p, sizeof(p)) > 0) { if (p.pr_vaddr == 0x0) { st->print("Warning: Address: 0x%x, Size: %dK, ",p.pr_vaddr, p.pr_size/1024, p.pr_mapname); st->print("Mapped file: %s, ", p.pr_mapname[0] == '\0' ? "None" : p.pr_mapname); @@ -2272,7 +2283,7 @@ static bool check_addr0(outputStream* st) { st->cr(); status = true; } - close(fd); + ::close(fd); } } return status; @@ -2520,8 +2531,6 @@ void os::jvm_path(char *buf, jint buflen) { // Use current module name "libjvm[_g].so" instead of // "libjvm"debug_only("_g")".so" since for fastdebug version // we should have "libjvm.so" but debug_only("_g") adds "_g"! - // It is used when we are choosing the HPI library's name - // "libhpi[_g].so" in hpi::initialize_get_interface(). len = strlen(buf); snprintf(buf + len, buflen-len, "/hotspot/libjvm%s.so", p); } else { @@ -2545,6 +2554,23 @@ void os::print_jni_name_suffix_on(outputStream* st, int args_size) { // no suffix required } +// This method is a copy of JDK's sysGetLastErrorString +// from src/solaris/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + + if (errno == 0) return 0; + + const char *s = ::strerror(errno); + size_t n = ::strlen(s); + if (n >= len) { + n = len - 1; + } + ::strncpy(buf, s, n); + buf[n] = '\0'; + return n; +} + // sun.misc.Signal @@ -3454,6 +3480,10 @@ size_t os::read(int fd, void *buf, unsigned int nBytes) { INTERRUPTIBLE_RETURN_INT_VM(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); } +size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + INTERRUPTIBLE_RETURN_INT(::read(fd, buf, nBytes), os::Solaris::clear_interrupted); +} + int os::sleep(Thread* thread, jlong millis, bool interruptible) { assert(thread == Thread::current(), "thread consistency check"); @@ -4623,16 +4653,16 @@ bool isT2_libthread() { #define ADR(x) ((uintptr_t)(x)) #define LWPINDEX(ary,ix) ((lwpstatus_t *)(((ary)->pr_entsize * (ix)) + (ADR((ary) + 1)))) - lwpFile = open("/proc/self/lstatus", O_RDONLY, 0); + lwpFile = ::open("/proc/self/lstatus", O_RDONLY, 0); if (lwpFile < 0) { if (ThreadPriorityVerbose) warning ("Couldn't open /proc/self/lstatus\n"); return false; } lwpSize = 16*1024; for (;;) { - lseek (lwpFile, 0, SEEK_SET); + ::lseek64 (lwpFile, 0, SEEK_SET); lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize); - if (read(lwpFile, lwpArray, lwpSize) < 0) { + if (::read(lwpFile, lwpArray, lwpSize) < 0) { if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n"); break; } @@ -4653,7 +4683,7 @@ bool isT2_libthread() { } FREE_C_HEAP_ARRAY(char, lwpArray); - close (lwpFile); + ::close (lwpFile); if (ThreadPriorityVerbose) { if (isT2) tty->print_cr("We are running with a T2 libthread\n"); else tty->print_cr("We are not running with a T2 libthread\n"); @@ -4849,7 +4879,7 @@ void os::init(void) { // if we need them. Solaris::misc_sym_init(); - int fd = open("/dev/zero", O_RDWR); + int fd = ::open("/dev/zero", O_RDWR); if (fd < 0) { fatal(err_msg("os::init: cannot open /dev/zero (%s)", strerror(errno))); } else { @@ -5019,13 +5049,6 @@ jint os::init_2(void) { } } - // Initialize HPI. - jint hpi_result = hpi::initialize(); - if (hpi_result != JNI_OK) { - tty->print_cr("There was an error trying to initialize the HPI library."); - return hpi_result; - } - // Calculate theoretical max. size of Threads to guard gainst // artifical out-of-memory situations, where all available address- // space has been reserved by thread stacks. Default stack size is 1Mb. @@ -5085,17 +5108,6 @@ void os::make_polling_page_readable(void) { // OS interface. -int os::stat(const char *path, struct stat *sbuf) { - char pathbuf[MAX_PATH]; - if (strlen(path) > MAX_PATH - 1) { - errno = ENAMETOOLONG; - return -1; - } - hpi::native_path(strcpy(pathbuf, path)); - return ::stat(pathbuf, sbuf); -} - - bool os::check_heap(bool force) { return true; } typedef int (*vsnprintf_t)(char* buf, size_t count, const char* fmt, va_list argptr); @@ -5140,6 +5152,125 @@ bool os::dir_is_empty(const char* path) { return result; } +// This code originates from JDK's sysOpen and open64_w +// from src/solaris/hpi/src/system_md.c + +#ifndef O_DELETE +#define O_DELETE 0x10000 +#endif + +// Open a file. Unlink the file immediately after open returns +// if the specified oflag has the O_DELETE flag set. +// O_DELETE is used only in j2se/src/share/native/java/util/zip/ZipFile.c + +int os::open(const char *path, int oflag, int mode) { + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + int fd; + int o_delete = (oflag & O_DELETE); + oflag = oflag & ~O_DELETE; + + fd = ::open(path, oflag, mode); + if (fd == -1) return -1; + + //If the open succeeded, the file might still be a directory + { + struct stat64 buf64; + int ret = ::fstat64(fd, &buf64); + int st_mode = buf64.st_mode; + + if (ret != -1) { + if ((st_mode & S_IFMT) == S_IFDIR) { + errno = EISDIR; + ::close(fd); + return -1; + } + } else { + ::close(fd); + return -1; + } + } + /* + * 32-bit Solaris systems suffer from: + * + * - an historical default soft limit of 256 per-process file + * descriptors that is too low for many Java programs. + * + * - a design flaw where file descriptors created using stdio + * fopen must be less than 256, _even_ when the first limit above + * has been raised. This can cause calls to fopen (but not calls to + * open, for example) to fail mysteriously, perhaps in 3rd party + * native code (although the JDK itself uses fopen). One can hardly + * criticize them for using this most standard of all functions. + * + * We attempt to make everything work anyways by: + * + * - raising the soft limit on per-process file descriptors beyond + * 256 + * + * - As of Solaris 10u4, we can request that Solaris raise the 256 + * stdio fopen limit by calling function enable_extended_FILE_stdio. + * This is done in init_2 and recorded in enabled_extended_FILE_stdio + * + * - If we are stuck on an old (pre 10u4) Solaris system, we can + * workaround the bug by remapping non-stdio file descriptors below + * 256 to ones beyond 256, which is done below. + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 6533291: Work around 32-bit Solaris stdio limit of 256 open files + * 6431278: Netbeans crash on 32 bit Solaris: need to call + * enable_extended_FILE_stdio() in VM initialisation + * Giri Mandalika's blog + * http://technopark02.blogspot.com/2005_05_01_archive.html + */ +#ifndef _LP64 + if ((!enabled_extended_FILE_stdio) && fd < 256) { + int newfd = ::fcntl(fd, F_DUPFD, 256); + if (newfd != -1) { + ::close(fd); + fd = newfd; + } + } +#endif // 32-bit Solaris + /* + * All file descriptors that are opened in the JVM and not + * specifically destined for a subprocess should have the + * close-on-exec flag set. If we don't set it, then careless 3rd + * party native code might fork and exec without closing all + * appropriate file descriptors (e.g. as we do in closeDescriptors in + * UNIXProcess.c), and this in turn might: + * + * - cause end-of-file to fail to be detected on some file + * descriptors, resulting in mysterious hangs, or + * + * - might cause an fopen in the subprocess to fail on a system + * suffering from bug 1085341. + * + * (Yes, the default setting of the close-on-exec flag is a Unix + * design flaw) + * + * See: + * 1085341: 32-bit stdio routines should support file descriptors >255 + * 4843136: (process) pipe file descriptor from Runtime.exec not being closed + * 6339493: (process) Runtime.exec does not close all file descriptors on Solaris 9 + */ +#ifdef FD_CLOEXEC + { + int flags = ::fcntl(fd, F_GETFD); + if (flags != -1) + ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC); + } +#endif + + if (o_delete != 0) { + ::unlink(path); + } + return fd; +} + // create binary file, rewriting existing file if required int os::create_binary_file(const char* path, bool rewrite_existing) { int oflags = O_WRONLY | O_CREAT; @@ -5159,6 +5290,55 @@ jlong os::seek_to_file_offset(int fd, jlong offset) { return (jlong)::lseek64(fd, (off64_t)offset, SEEK_SET); } +jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::lseek64(fd, offset, whence); +} + +char * os::native_path(char *path) { + return path; +} + +int os::ftruncate(int fd, jlong length) { + return ::ftruncate64(fd, length); +} + +int os::fsync(int fd) { + RESTARTABLE_RETURN_INT(::fsync(fd)); +} + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + int mode; + struct stat64 buf64; + + if (::fstat64(fd, &buf64) >= 0) { + mode = buf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { + /* + * XXX: is the following call interruptible? If so, this might + * need to go through the INTERRUPT_IO() wrapper as for other + * blocking, interruptible calls in this file. + */ + int n,ioctl_return; + + INTERRUPTIBLE(::ioctl(fd, FIONREAD, &n),ioctl_return,os::Solaris::clear_interrupted); + if (ioctl_return>= 0) { + *bytes = n; + return 1; + } + } + } + if ((cur = ::lseek64(fd, 0L, SEEK_CUR)) == -1) { + return 0; + } else if ((end = ::lseek64(fd, 0L, SEEK_END)) == -1) { + return 0; + } else if (::lseek64(fd, cur, SEEK_SET) == -1) { + return 0; + } + *bytes = end - cur; + return 1; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -5217,7 +5397,7 @@ void os::pause() { int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd != -1) { struct stat buf; - close(fd); + ::close(fd); while (::stat(filename, &buf) == 0) { (void)::poll(NULL, 0, 100); } @@ -5414,16 +5594,16 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { sprintf(proc_name, "/proc/%d/lwp/%d/lwpusage", getpid(), thread->osthread()->lwp_id()); - fd = open(proc_name, O_RDONLY); + fd = ::open(proc_name, O_RDONLY); if ( fd == -1 ) return -1; do { - count = pread(fd, + count = ::pread(fd, (void *)&prusage.pr_utime, thr_time_size, thr_time_off); } while (count < 0 && errno == EINTR); - close(fd); + ::close(fd); if ( count < 0 ) return -1; if (user_sys_cpu_time) { @@ -6095,4 +6275,127 @@ bool os::is_headless_jre() { return true; } +size_t os::write(int fd, const void *buf, unsigned int nBytes) { + INTERRUPTIBLE_RETURN_INT(::write(fd, buf, nBytes), os::Solaris::clear_interrupted); +} + +int os::close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +int os::socket_close(int fd) { + RESTARTABLE_RETURN_INT(::close(fd)); +} + +int os::recv(int fd, char *buf, int nBytes, int flags) { + INTERRUPTIBLE_RETURN_INT(::recv(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); +} + + +int os::send(int fd, char *buf, int nBytes, int flags) { + INTERRUPTIBLE_RETURN_INT(::send(fd, buf, nBytes, flags), os::Solaris::clear_interrupted); +} + +int os::raw_send(int fd, char *buf, int nBytes, int flags) { + RESTARTABLE_RETURN_INT(::send(fd, buf, nBytes, flags)); +} + +// As both poll and select can be interrupted by signals, we have to be +// prepared to restart the system call after updating the timeout, unless +// a poll() is done with timeout == -1, in which case we repeat with this +// "wait forever" value. + +int os::timeout(int fd, long timeout) { + int res; + struct timeval t; + julong prevtime, newtime; + static const char* aNull = 0; + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN; + + gettimeofday(&t, &aNull); + prevtime = ((julong)t.tv_sec * 1000) + t.tv_usec / 1000; + + for(;;) { + INTERRUPTIBLE_NORESTART(::poll(&pfd, 1, timeout), res, os::Solaris::clear_interrupted); + if(res == OS_ERR && errno == EINTR) { + if(timeout != -1) { + gettimeofday(&t, &aNull); + newtime = ((julong)t.tv_sec * 1000) + t.tv_usec /1000; + timeout -= newtime - prevtime; + if(timeout <= 0) + return OS_OK; + prevtime = newtime; + } + } else return res; + } +} + +int os::connect(int fd, struct sockaddr *him, int len) { + int _result; + INTERRUPTIBLE_NORESTART(::connect(fd, him, len), _result, + os::Solaris::clear_interrupted); + + // Depending on when thread interruption is reset, _result could be + // one of two values when errno == EINTR + + if (((_result == OS_INTRPT) || (_result == OS_ERR)) + && (errno == EINTR)) { + /* restarting a connect() changes its errno semantics */ + INTERRUPTIBLE(::connect(fd, him, len), _result, + os::Solaris::clear_interrupted); + /* undo these changes */ + if (_result == OS_ERR) { + if (errno == EALREADY) { + errno = EINPROGRESS; /* fall through */ + } else if (errno == EISCONN) { + errno = 0; + return OS_OK; + } + } + } + return _result; + } + +int os::accept(int fd, struct sockaddr *him, int *len) { + if (fd < 0) + return OS_ERR; + INTERRUPTIBLE_RETURN_INT((int)::accept(fd, him,\ + (socklen_t*) len), os::Solaris::clear_interrupted); + } + +int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + //%%note jvm_r11 + INTERRUPTIBLE_RETURN_INT((int)::recvfrom(fd, buf, nBytes,\ + flags, from, fromlen), os::Solaris::clear_interrupted); +} + +int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + //%%note jvm_r11 + INTERRUPTIBLE_RETURN_INT((int)::sendto(fd, buf, len, flags,\ + to, tolen), os::Solaris::clear_interrupted); +} + +int os::socket_available(int fd, jint *pbytes) { + if (fd < 0) + return OS_OK; + + int ret; + + RESTARTABLE(::ioctl(fd, FIONREAD, pbytes), ret); + + //%% note ioctl can return 0 when successful, JVM_SocketAvailable + // is expected to return 0 on failure and 1 on success to the jdk. + + return (ret == OS_ERR) ? 0 : 1; +} + + +int os::bind(int fd, struct sockaddr *him, int len) { + INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\ + os::Solaris::clear_interrupted); +} diff --git a/src/os/solaris/vm/os_solaris.inline.hpp b/src/os/solaris/vm/os_solaris.inline.hpp index 15ba113378a3b635f277ffc7f1ffdf2725074e05..b1e42a52dcf07783109f3c5299d9ebb22577c9c1 100644 --- a/src/os/solaris/vm/os_solaris.inline.hpp +++ b/src/os/solaris/vm/os_solaris.inline.hpp @@ -36,6 +36,16 @@ # include "orderAccess_solaris_sparc.inline.hpp" #endif +// System includes +#include +#include +#include +#include +#include +#include +#include +#include + inline const char* os::file_separator() { return "/"; } inline const char* os::line_separator() { return "\n"; } inline const char* os::path_separator() { return ":"; } @@ -69,21 +79,19 @@ inline void os::split_reserved_memory(char *base, size_t size, // Bang the shadow pages if they need to be touched to be mapped. inline void os::bang_stack_shadow_pages() { } +inline void os::dll_unload(void *lib) { ::dlclose(lib); } -inline DIR* os::opendir(const char* dirname) -{ +inline DIR* os::opendir(const char* dirname) { assert(dirname != NULL, "just checking"); return ::opendir(dirname); } -inline int os::readdir_buf_size(const char *path) -{ +inline int os::readdir_buf_size(const char *path) { int size = pathconf(path, _PC_NAME_MAX); return (size < 0 ? MAXPATHLEN : size) + sizeof(dirent) + 1; } -inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) -{ +inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) { assert(dirp != NULL, "just checking"); #if defined(_LP64) || defined(_GNU_SOURCE) dirent* p; @@ -99,9 +107,8 @@ inline struct dirent* os::readdir(DIR* dirp, dirent* dbuf) #endif // defined(_LP64) || defined(_GNU_SOURCE) } -inline int os::closedir(DIR *dirp) -{ - assert(dirp != NULL, "just checking"); +inline int os::closedir(DIR *dirp) { + assert(dirp != NULL, "argument is NULL"); return ::closedir(dirp); } @@ -222,4 +229,38 @@ do { \ inline bool os::numa_has_static_binding() { return false; } inline bool os::numa_has_group_homing() { return true; } +inline int os::socket(int domain, int type, int protocol) { + return ::socket(domain, type, protocol); +} + +inline int os::listen(int fd, int count) { + if (fd < 0) return OS_ERR; + + return ::listen(fd, count); +} + +inline int os::socket_shutdown(int fd, int howto){ + return ::shutdown(fd, howto); +} + +inline int os::get_sock_name(int fd, struct sockaddr *him, int *len){ + return ::getsockname(fd, him, (socklen_t*) len); +} + +inline int os::get_host_name(char* name, int namelen){ + return ::gethostname(name, namelen); +} + +inline struct hostent* os::get_host_by_name(char* name) { + return ::gethostbyname(name); +} +inline int os::get_sock_opt(int fd, int level, int optname, + char *optval, int* optlen){ + return ::getsockopt(fd, level, optname, optval, (socklen_t*) optlen); +} + +inline int os::set_sock_opt(int fd, int level, int optname, + const char *optval, int optlen){ + return ::setsockopt(fd, level, optname, optval, optlen); +} #endif // OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP diff --git a/src/os/windows/launcher/java_md.c b/src/os/windows/launcher/java_md.c new file mode 100644 index 0000000000000000000000000000000000000000..715be6cd0f583c4d28d5bae207375e5b81ee060c --- /dev/null +++ b/src/os/windows/launcher/java_md.c @@ -0,0 +1,1465 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "java.h" +#ifndef GAMMA +#include "version_comp.h" +#endif + +#define JVM_DLL "jvm.dll" +#define JAVA_DLL "java.dll" +#define CRT_DLL "msvcr71.dll" + +/* + * Prototypes. + */ +static jboolean GetPublicJREHome(char *path, jint pathsize); +static jboolean GetJVMPath(const char *jrepath, const char *jvmtype, + char *jvmpath, jint jvmpathsize); +static jboolean GetJREPath(char *path, jint pathsize); +static void EnsureJreInstallation(const char *jrepath); + +/* We supports warmup for UI stack that is performed in parallel + * to VM initialization. + * This helps to improve startup of UI application as warmup phase + * might be long due to initialization of OS or hardware resources. + * It is not CPU bound and therefore it does not interfere with VM init. + * Obviously such warmup only has sense for UI apps and therefore it needs + * to be explicitly requested by passing -Dsun.awt.warmup=true property + * (this is always the case for plugin/javaws). + * + * Implementation launches new thread after VM starts and use it to perform + * warmup code (platform dependent). + * This thread is later reused as AWT toolkit thread as graphics toolkit + * often assume that they are used from the same thread they were launched on. + * + * At the moment we only support warmup for D3D. It only possible on windows + * and only if other flags do not prohibit this (e.g. OpenGL support requested). + */ +#undef ENABLE_AWT_PRELOAD +#ifndef JAVA_ARGS /* turn off AWT preloading for javac, jar, etc */ + #ifdef _X86_ /* for now disable AWT preloading for 64bit */ + #define ENABLE_AWT_PRELOAD + #endif +#endif + +#ifdef ENABLE_AWT_PRELOAD +/* "AWT was preloaded" flag; + * Turned on by AWTPreload(). + */ +int awtPreloaded = 0; + +/* Calls a function with the name specified. + * The function must be int(*fn)(void). + */ +int AWTPreload(const char *funcName); +/* Stops AWT preloading. */ +void AWTPreloadStop(); + +/* D3D preloading */ +/* -1: not initialized; 0: OFF, 1: ON */ +int awtPreloadD3D = -1; +/* Command line parameter to swith D3D preloading on. */ +#define PARAM_PRELOAD_D3D "-Dsun.awt.warmup" +/* D3D/OpenGL management parameters (may disable D3D preloading) */ +#define PARAM_NODDRAW "-Dsun.java2d.noddraw" +#define PARAM_D3D "-Dsun.java2d.d3d" +#define PARAM_OPENGL "-Dsun.java2d.opengl" +/* funtion in awt.dll (src/windows/native/sun/java2d/d3d/D3DPipelineManager.cpp) */ +#define D3D_PRELOAD_FUNC "preloadD3D" + + +/* Extracts value of a parameter with the specified name + * from command line argument (returns pointer in the argument). + * Returns NULL if the argument does not contains the parameter. + * e.g.: + * GetParamValue("theParam", "theParam=value") returns pointer to "value". + */ +const char * GetParamValue(const char *paramName, const char *arg) { + int nameLen = strlen(paramName); + if (strncmp(paramName, arg, nameLen) == 0) { + // arg[nameLen] is valid (may contain final NULL) + if (arg[nameLen] == '=') { + return arg + nameLen + 1; + } + } + return NULL; +} + +/* Checks if commandline argument contains property specified + * and analyze it as boolean property (true/false). + * Returns -1 if the argument does not contain the parameter; + * Returns 1 if the argument contains the parameter and its value is "true"; + * Returns 0 if the argument contains the parameter and its value is "false". + */ +int GetBoolParamValue(const char *paramName, const char *arg) { + const char * paramValue = GetParamValue(paramName, arg); + if (paramValue != NULL) { + if (stricmp(paramValue, "true") == 0) { + return 1; + } + if (stricmp(paramValue, "false") == 0) { + return 0; + } + } + return -1; +} +#endif /* ENABLE_AWT_PRELOAD */ + + +const char * +GetArch() +{ + +#ifdef _M_AMD64 + return "amd64"; +#elif defined(_M_IA64) + return "ia64"; +#else + return "i386"; +#endif +} + +/* + * + */ +void +CreateExecutionEnvironment(int *_argc, + char ***_argv, + char jrepath[], + jint so_jrepath, + char jvmpath[], + jint so_jvmpath, + char **original_argv) { +#ifndef GAMMA + char * jvmtype; + + /* Find out where the JRE is that we will be using. */ + if (!GetJREPath(jrepath, so_jrepath)) { + ReportErrorMessage("Error: could not find Java SE Runtime Environment.", + JNI_TRUE); + exit(2); + } + + /* Do this before we read jvm.cfg */ + EnsureJreInstallation(jrepath); + + /* Find the specified JVM type */ + if (ReadKnownVMs(jrepath, (char*)GetArch(), JNI_FALSE) < 1) { + ReportErrorMessage("Error: no known VMs. (check for corrupt jvm.cfg file)", + JNI_TRUE); + exit(1); + } + jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); + + jvmpath[0] = '\0'; + if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { + char * message=NULL; + const char * format = "Error: no `%s' JVM at `%s'."; + message = (char *)JLI_MemAlloc((strlen(format)+strlen(jvmtype)+ + strlen(jvmpath)) * sizeof(char)); + sprintf(message,format, jvmtype, jvmpath); + ReportErrorMessage(message, JNI_TRUE); + exit(4); + } + /* If we got here, jvmpath has been correctly initialized. */ + +#else /* ifndef GAMMA */ + + /* + * gamma launcher is simpler in that it doesn't handle VM flavors, data + * model, etc. Assuming everything is set-up correctly + * all we need to do here is to return correct path names. See also + * GetJVMPath() and GetApplicationHome(). + */ + + { + if (!GetJREPath(jrepath, so_jrepath) ) { + ReportErrorMessage("Error: could not find Java SE Runtime Environment.", + JNI_TRUE); + exit(2); + } + + if (!GetJVMPath(jrepath, NULL, jvmpath, so_jvmpath)) { + char * message=NULL; + const char * format = "Error: no JVM at `%s'."; + message = (char *)JLI_MemAlloc((strlen(format)+ + strlen(jvmpath)) * sizeof(char)); + sprintf(message, format, jvmpath); + ReportErrorMessage(message, JNI_TRUE); + exit(4); + } + } + +#endif /* ifndef GAMMA */ + +} + + +static jboolean +LoadMSVCRT() +{ + // Only do this once + static int loaded = 0; + char crtpath[MAXPATHLEN]; + + if (!loaded) { + /* + * The Microsoft C Runtime Library needs to be loaded first. A copy is + * assumed to be present in the "JRE path" directory. If it is not found + * there (or "JRE path" fails to resolve), skip the explicit load and let + * nature take its course, which is likely to be a failure to execute. + */ + if (GetJREPath(crtpath, MAXPATHLEN)) { + (void)strcat(crtpath, "\\bin\\" CRT_DLL); /* Add crt dll */ + if (_launcher_debug) { + printf("CRT path is %s\n", crtpath); + } + if (_access(crtpath, 0) == 0) { + if (LoadLibrary(crtpath) == 0) { + ReportErrorMessage2("Error loading: %s", crtpath, JNI_TRUE); + return JNI_FALSE; + } + } + } + loaded = 1; + } + return JNI_TRUE; +} + +/* + * The preJVMStart is a function in the jkernel.dll, which + * performs the final step of synthesizing back the decomposed + * modules (partial install) to the full JRE. Any tool which + * uses the JRE must peform this step to ensure the complete synthesis. + * The EnsureJreInstallation function calls preJVMStart based on + * the conditions outlined below, noting that the operation + * will fail silently if any of conditions are not met. + * NOTE: this call must be made before jvm.dll is loaded, or jvm.cfg + * is read, since jvm.cfg will be modified by the preJVMStart. + * 1. Are we on a supported platform. + * 2. Find the location of the JRE or the Kernel JRE. + * 3. check existence of JREHOME/lib/bundles + * 4. check jkernel.dll and invoke the entry-point + */ +typedef VOID (WINAPI *PREJVMSTART)(); + +static void +EnsureJreInstallation(const char* jrepath) +{ + HINSTANCE handle; + char tmpbuf[MAXPATHLEN]; + PREJVMSTART PreJVMStart; + struct stat s; + + /* 32 bit windows only please */ + if (strcmp(GetArch(), "i386") != 0 ) { + if (_launcher_debug) { + printf("EnsureJreInstallation:unsupported platform\n"); + } + return; + } + /* Does our bundle directory exist ? */ + strcpy(tmpbuf, jrepath); + strcat(tmpbuf, "\\lib\\bundles"); + if (stat(tmpbuf, &s) != 0) { + if (_launcher_debug) { + printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf); + } + return; + } + /* Does our jkernel dll exist ? */ + strcpy(tmpbuf, jrepath); + strcat(tmpbuf, "\\bin\\jkernel.dll"); + if (stat(tmpbuf, &s) != 0) { + if (_launcher_debug) { + printf("EnsureJreInstallation:<%s>:not found\n", tmpbuf); + } + return; + } + /* The Microsoft C Runtime Library needs to be loaded first. */ + if (!LoadMSVCRT()) { + if (_launcher_debug) { + printf("EnsureJreInstallation:could not load C runtime DLL\n"); + } + return; + } + /* Load the jkernel.dll */ + if ((handle = LoadLibrary(tmpbuf)) == 0) { + if (_launcher_debug) { + printf("EnsureJreInstallation:%s:load failed\n", tmpbuf); + } + return; + } + /* Get the function address */ + PreJVMStart = (PREJVMSTART)GetProcAddress(handle, "preJVMStart"); + if (PreJVMStart == NULL) { + if (_launcher_debug) { + printf("EnsureJreInstallation:preJVMStart:function lookup failed\n"); + } + FreeLibrary(handle); + return; + } + PreJVMStart(); + if (_launcher_debug) { + printf("EnsureJreInstallation:preJVMStart:called\n"); + } + FreeLibrary(handle); + return; +} + +/* + * Find path to JRE based on .exe's location or registry settings. + */ +jboolean +GetJREPath(char *path, jint pathsize) +{ + char javadll[MAXPATHLEN]; + struct stat s; + + if (GetApplicationHome(path, pathsize)) { + /* Is JRE co-located with the application? */ + sprintf(javadll, "%s\\bin\\" JAVA_DLL, path); + if (stat(javadll, &s) == 0) { + goto found; + } + + /* Does this app ship a private JRE in \jre directory? */ + sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path); + if (stat(javadll, &s) == 0) { + strcat(path, "\\jre"); + goto found; + } + } + +#ifndef GAMMA + /* Look for a public JRE on this machine. */ + if (GetPublicJREHome(path, pathsize)) { + goto found; + } +#endif + + fprintf(stderr, "Error: could not find " JAVA_DLL "\n"); + return JNI_FALSE; + + found: + if (_launcher_debug) + printf("JRE path is %s\n", path); + return JNI_TRUE; +} + +/* + * Given a JRE location and a JVM type, construct what the name the + * JVM shared library will be. Return true, if such a library + * exists, false otherwise. + */ +static jboolean +GetJVMPath(const char *jrepath, const char *jvmtype, + char *jvmpath, jint jvmpathsize) +{ + struct stat s; + +#ifndef GAMMA + if (strchr(jvmtype, '/') || strchr(jvmtype, '\\')) { + sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype); + } else { + sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); + } +#else + /* + * For gamma launcher, JVM is either built-in or in the same directory. + * Either way we return "/jvm.dll" where is the + * directory where gamma launcher is located. + */ + + char *p; + GetModuleFileName(0, jvmpath, jvmpathsize); + + p = strrchr(jvmpath, '\\'); + if (p) { + /* replace executable name with libjvm.so */ + snprintf(p + 1, jvmpathsize - (p + 1 - jvmpath), "%s", JVM_DLL); + } else { + /* this case shouldn't happen */ + snprintf(jvmpath, jvmpathsize, "%s", JVM_DLL); + } +#endif /* ifndef GAMMA */ + + if (stat(jvmpath, &s) == 0) { + return JNI_TRUE; + } else { + return JNI_FALSE; + } +} + +/* + * Load a jvm from "jvmpath" and initialize the invocation functions. + */ +jboolean +LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) +{ +#ifdef GAMMA + /* JVM is directly linked with gamma launcher; no Loadlibrary() */ + ifn->CreateJavaVM = JNI_CreateJavaVM; + ifn->GetDefaultJavaVMInitArgs = JNI_GetDefaultJavaVMInitArgs; + return JNI_TRUE; +#else + HINSTANCE handle; + + if (_launcher_debug) { + printf("JVM path is %s\n", jvmpath); + } + + /* The Microsoft C Runtime Library needs to be loaded first. */ + LoadMSVCRT(); + + /* Load the Java VM DLL */ + if ((handle = LoadLibrary(jvmpath)) == 0) { + ReportErrorMessage2("Error loading: %s", (char *)jvmpath, JNI_TRUE); + return JNI_FALSE; + } + + /* Now get the function addresses */ + ifn->CreateJavaVM = + (void *)GetProcAddress(handle, "JNI_CreateJavaVM"); + ifn->GetDefaultJavaVMInitArgs = + (void *)GetProcAddress(handle, "JNI_GetDefaultJavaVMInitArgs"); + if (ifn->CreateJavaVM == 0 || ifn->GetDefaultJavaVMInitArgs == 0) { + ReportErrorMessage2("Error: can't find JNI interfaces in: %s", + (char *)jvmpath, JNI_TRUE); + return JNI_FALSE; + } + + return JNI_TRUE; +#endif /* ifndef GAMMA */ +} + +/* + * If app is "c:\foo\bin\javac", then put "c:\foo" into buf. + */ +jboolean +GetApplicationHome(char *buf, jint bufsize) +{ +#ifndef GAMMA + char *cp; + GetModuleFileName(0, buf, bufsize); + *strrchr(buf, '\\') = '\0'; /* remove .exe file name */ + if ((cp = strrchr(buf, '\\')) == 0) { + /* This happens if the application is in a drive root, and + * there is no bin directory. */ + buf[0] = '\0'; + return JNI_FALSE; + } + *cp = '\0'; /* remove the bin\ part */ + return JNI_TRUE; + +#else /* ifndef GAMMA */ + + /* gamma launcher uses JAVA_HOME or ALT_JAVA_HOME environment variable to find JDK/JRE */ + char* java_home_var = getenv("ALT_JAVA_HOME"); + if (java_home_var == NULL) { + java_home_var = getenv("JAVA_HOME"); + } + if (java_home_var == NULL) { + printf("JAVA_HOME or ALT_JAVA_HOME must point to a valid JDK/JRE to run gamma\n"); + return JNI_FALSE; + } + snprintf(buf, bufsize, "%s", java_home_var); + return JNI_TRUE; +#endif /* ifndef GAMMA */ +} + +#ifdef JAVAW +__declspec(dllimport) char **__initenv; + +int WINAPI +WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow) +{ + int ret; + + __initenv = _environ; + ret = main(__argc, __argv); + + return ret; +} +#endif + +#ifndef GAMMA + +/* + * Helpers to look in the registry for a public JRE. + */ + /* Same for 1.5.0, 1.5.1, 1.5.2 etc. */ +#define DOTRELEASE JDK_MAJOR_VERSION "." JDK_MINOR_VERSION +#define JRE_KEY "Software\\JavaSoft\\Java Runtime Environment" + +static jboolean +GetStringFromRegistry(HKEY key, const char *name, char *buf, jint bufsize) +{ + DWORD type, size; + + if (RegQueryValueEx(key, name, 0, &type, 0, &size) == 0 + && type == REG_SZ + && (size < (unsigned int)bufsize)) { + if (RegQueryValueEx(key, name, 0, 0, buf, &size) == 0) { + return JNI_TRUE; + } + } + return JNI_FALSE; +} + +static jboolean +GetPublicJREHome(char *buf, jint bufsize) +{ + HKEY key, subkey; + char version[MAXPATHLEN]; + + /* + * Note: There is a very similar implementation of the following + * registry reading code in the Windows java control panel (javacp.cpl). + * If there are bugs here, a similar bug probably exists there. Hence, + * changes here require inspection there. + */ + + /* Find the current version of the JRE */ + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, JRE_KEY, 0, KEY_READ, &key) != 0) { + fprintf(stderr, "Error opening registry key '" JRE_KEY "'\n"); + return JNI_FALSE; + } + + if (!GetStringFromRegistry(key, "CurrentVersion", + version, sizeof(version))) { + fprintf(stderr, "Failed reading value of registry key:\n\t" + JRE_KEY "\\CurrentVersion\n"); + RegCloseKey(key); + return JNI_FALSE; + } + + if (strcmp(version, DOTRELEASE) != 0) { + fprintf(stderr, "Registry key '" JRE_KEY "\\CurrentVersion'\nhas " + "value '%s', but '" DOTRELEASE "' is required.\n", version); + RegCloseKey(key); + return JNI_FALSE; + } + + /* Find directory where the current version is installed. */ + if (RegOpenKeyEx(key, version, 0, KEY_READ, &subkey) != 0) { + fprintf(stderr, "Error opening registry key '" + JRE_KEY "\\%s'\n", version); + RegCloseKey(key); + return JNI_FALSE; + } + + if (!GetStringFromRegistry(subkey, "JavaHome", buf, bufsize)) { + fprintf(stderr, "Failed reading value of registry key:\n\t" + JRE_KEY "\\%s\\JavaHome\n", version); + RegCloseKey(key); + RegCloseKey(subkey); + return JNI_FALSE; + } + + if (_launcher_debug) { + char micro[MAXPATHLEN]; + if (!GetStringFromRegistry(subkey, "MicroVersion", micro, + sizeof(micro))) { + printf("Warning: Can't read MicroVersion\n"); + micro[0] = '\0'; + } + printf("Version major.minor.micro = %s.%s\n", version, micro); + } + + RegCloseKey(key); + RegCloseKey(subkey); + return JNI_TRUE; +} + +#endif /* ifndef GAMMA */ + +/* + * Support for doing cheap, accurate interval timing. + */ +static jboolean counterAvailable = JNI_FALSE; +static jboolean counterInitialized = JNI_FALSE; +static LARGE_INTEGER counterFrequency; + +jlong CounterGet() +{ + LARGE_INTEGER count; + + if (!counterInitialized) { + counterAvailable = QueryPerformanceFrequency(&counterFrequency); + counterInitialized = JNI_TRUE; + } + if (!counterAvailable) { + return 0; + } + QueryPerformanceCounter(&count); + return (jlong)(count.QuadPart); +} + +jlong Counter2Micros(jlong counts) +{ + if (!counterAvailable || !counterInitialized) { + return 0; + } + return (counts * 1000 * 1000)/counterFrequency.QuadPart; +} + +void ReportErrorMessage(char * message, jboolean always) { +#ifdef JAVAW + if (message != NULL) { + MessageBox(NULL, message, "Java Virtual Machine Launcher", + (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); + } +#else + if (always) { + fprintf(stderr, "%s\n", message); + } +#endif +} + +void ReportErrorMessage2(char * format, char * string, jboolean always) { + /* + * The format argument must be a printf format string with one %s + * argument, which is passed the string argument. + */ +#ifdef JAVAW + size_t size; + char * message; + size = strlen(format) + strlen(string); + message = (char*)JLI_MemAlloc(size*sizeof(char)); + sprintf(message, (const char *)format, string); + + if (message != NULL) { + MessageBox(NULL, message, "Java Virtual Machine Launcher", + (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); + JLI_MemFree(message); + } +#else + if (always) { + fprintf(stderr, (const char *)format, string); + fprintf(stderr, "\n"); + } +#endif +} + +/* + * As ReportErrorMessage2 (above) except the system message (if any) + * associated with this error is written to a second %s format specifier + * in the format argument. + */ +void ReportSysErrorMessage2(char * format, char * string, jboolean always) { + int save_errno = errno; + DWORD errval; + int freeit = 0; + char *errtext = NULL; + + if ((errval = GetLastError()) != 0) { /* Platform SDK / DOS Error */ + int n = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM| + FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, errval, 0, (LPTSTR)&errtext, 0, NULL); + if (errtext == NULL || n == 0) { /* Paranoia check */ + errtext = ""; + n = 0; + } else { + freeit = 1; + if (n > 2) { /* Drop final CR, LF */ + if (errtext[n - 1] == '\n') n--; + if (errtext[n - 1] == '\r') n--; + errtext[n] = '\0'; + } + } + } else /* C runtime error that has no corresponding DOS error code */ + errtext = strerror(save_errno); + +#ifdef JAVAW + { + size_t size; + char * message; + size = strlen(format) + strlen(string) + strlen(errtext); + message = (char*)JLI_MemAlloc(size*sizeof(char)); + sprintf(message, (const char *)format, string, errtext); + + if (message != NULL) { + MessageBox(NULL, message, "Java Virtual Machine Launcher", + (MB_OK|MB_ICONSTOP|MB_APPLMODAL)); + JLI_MemFree(message); + } + } +#else + if (always) { + fprintf(stderr, (const char *)format, string, errtext); + fprintf(stderr, "\n"); + } +#endif + if (freeit) + (void)LocalFree((HLOCAL)errtext); +} + +void ReportExceptionDescription(JNIEnv * env) { +#ifdef JAVAW + /* + * This code should be replaced by code which opens a window with + * the exception detail message. + */ + (*env)->ExceptionDescribe(env); +#else + (*env)->ExceptionDescribe(env); +#endif +} + + +/* + * Return JNI_TRUE for an option string that has no effect but should + * _not_ be passed on to the vm; return JNI_FALSE otherwise. On + * windows, there are no options that should be screened in this + * manner. + */ +jboolean RemovableMachineDependentOption(char * option) { +#ifdef ENABLE_AWT_PRELOAD + if (awtPreloadD3D < 0) { + /* Tests the command line parameter only if not set yet. */ + if (GetBoolParamValue(PARAM_PRELOAD_D3D, option) == 1) { + awtPreloadD3D = 1; + } + } + if (awtPreloadD3D != 0) { + /* Don't test the command line parameters if already disabled. */ + if (GetBoolParamValue(PARAM_NODDRAW, option) == 1 + || GetBoolParamValue(PARAM_D3D, option) == 0 + || GetBoolParamValue(PARAM_OPENGL, option) == 1) + { + awtPreloadD3D = 0; + } + } +#endif /* ENABLE_AWT_PRELOAD */ + + return JNI_FALSE; +} + +void PrintMachineDependentOptions() { + return; +} + +#ifndef GAMMA + +jboolean +ServerClassMachine() { + jboolean result = JNI_FALSE; +#if defined(NEVER_ACT_AS_SERVER_CLASS_MACHINE) + result = JNI_FALSE; +#elif defined(ALWAYS_ACT_AS_SERVER_CLASS_MACHINE) + result = JNI_TRUE; +#endif + return result; +} + +/* + * Determine if there is an acceptable JRE in the registry directory top_key. + * Upon locating the "best" one, return a fully qualified path to it. + * "Best" is defined as the most advanced JRE meeting the constraints + * contained in the manifest_info. If no JRE in this directory meets the + * constraints, return NULL. + * + * It doesn't matter if we get an error reading the registry, or we just + * don't find anything interesting in the directory. We just return NULL + * in either case. + */ +static char * +ProcessDir(manifest_info* info, HKEY top_key) { + DWORD index = 0; + HKEY ver_key; + char name[MAXNAMELEN]; + int len; + char *best = NULL; + + /* + * Enumerate "/SOFTWARE/JavaSoft/Java Runtime Environment" + * searching for the best available version. + */ + while (RegEnumKey(top_key, index, name, MAXNAMELEN) == ERROR_SUCCESS) { + index++; + if (JLI_AcceptableRelease(name, info->jre_version)) + if ((best == NULL) || (JLI_ExactVersionId(name, best) > 0)) { + if (best != NULL) + JLI_MemFree(best); + best = JLI_StringDup(name); + } + } + + /* + * Extract "JavaHome" from the "best" registry directory and return + * that path. If no appropriate version was located, or there is an + * error in extracting the "JavaHome" string, return null. + */ + if (best == NULL) + return (NULL); + else { + if (RegOpenKeyEx(top_key, best, 0, KEY_READ, &ver_key) + != ERROR_SUCCESS) { + JLI_MemFree(best); + if (ver_key != NULL) + RegCloseKey(ver_key); + return (NULL); + } + JLI_MemFree(best); + len = MAXNAMELEN; + if (RegQueryValueEx(ver_key, "JavaHome", NULL, NULL, (LPBYTE)name, &len) + != ERROR_SUCCESS) { + if (ver_key != NULL) + RegCloseKey(ver_key); + return (NULL); + } + if (ver_key != NULL) + RegCloseKey(ver_key); + return (JLI_StringDup(name)); + } +} + +/* + * This is the global entry point. It examines the host for the optimal + * JRE to be used by scanning a set of registry entries. This set of entries + * is hardwired on Windows as "Software\JavaSoft\Java Runtime Environment" + * under the set of roots "{ HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }". + * + * This routine simply opens each of these registry directories before passing + * control onto ProcessDir(). + */ +char * +LocateJRE(manifest_info* info) { + HKEY key = NULL; + char *path; + int key_index; + HKEY root_keys[2] = { HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE }; + + for (key_index = 0; key_index <= 1; key_index++) { + if (RegOpenKeyEx(root_keys[key_index], JRE_KEY, 0, KEY_READ, &key) + == ERROR_SUCCESS) + if ((path = ProcessDir(info, key)) != NULL) { + if (key != NULL) + RegCloseKey(key); + return (path); + } + if (key != NULL) + RegCloseKey(key); + } + return NULL; +} + + +/* + * Local helper routine to isolate a single token (option or argument) + * from the command line. + * + * This routine accepts a pointer to a character pointer. The first + * token (as defined by MSDN command-line argument syntax) is isolated + * from that string. + * + * Upon return, the input character pointer pointed to by the parameter s + * is updated to point to the remainding, unscanned, portion of the string, + * or to a null character if the entire string has been consummed. + * + * This function returns a pointer to a null-terminated string which + * contains the isolated first token, or to the null character if no + * token could be isolated. + * + * Note the side effect of modifying the input string s by the insertion + * of a null character, making it two strings. + * + * See "Parsing C Command-Line Arguments" in the MSDN Library for the + * parsing rule details. The rule summary from that specification is: + * + * * Arguments are delimited by white space, which is either a space or a tab. + * + * * A string surrounded by double quotation marks is interpreted as a single + * argument, regardless of white space contained within. A quoted string can + * be embedded in an argument. Note that the caret (^) is not recognized as + * an escape character or delimiter. + * + * * A double quotation mark preceded by a backslash, \", is interpreted as a + * literal double quotation mark ("). + * + * * Backslashes are interpreted literally, unless they immediately precede a + * double quotation mark. + * + * * If an even number of backslashes is followed by a double quotation mark, + * then one backslash (\) is placed in the argv array for every pair of + * backslashes (\\), and the double quotation mark (") is interpreted as a + * string delimiter. + * + * * If an odd number of backslashes is followed by a double quotation mark, + * then one backslash (\) is placed in the argv array for every pair of + * backslashes (\\) and the double quotation mark is interpreted as an + * escape sequence by the remaining backslash, causing a literal double + * quotation mark (") to be placed in argv. + */ +static char* +nextarg(char** s) { + char *p = *s; + char *head; + int slashes = 0; + int inquote = 0; + + /* + * Strip leading whitespace, which MSDN defines as only space or tab. + * (Hence, no locale specific "isspace" here.) + */ + while (*p != (char)0 && (*p == ' ' || *p == '\t')) + p++; + head = p; /* Save the start of the token to return */ + + /* + * Isolate a token from the command line. + */ + while (*p != (char)0 && (inquote || !(*p == ' ' || *p == '\t'))) { + if (*p == '\\' && *(p+1) == '"' && slashes % 2 == 0) + p++; + else if (*p == '"') + inquote = !inquote; + slashes = (*p++ == '\\') ? slashes + 1 : 0; + } + + /* + * If the token isolated isn't already terminated in a "char zero", + * then replace the whitespace character with one and move to the + * next character. + */ + if (*p != (char)0) + *p++ = (char)0; + + /* + * Update the parameter to point to the head of the remaining string + * reflecting the command line and return a pointer to the leading + * token which was isolated from the command line. + */ + *s = p; + return (head); +} + +/* + * Local helper routine to return a string equivalent to the input string + * s, but with quotes removed so the result is a string as would be found + * in argv[]. The returned string should be freed by a call to JLI_MemFree(). + * + * The rules for quoting (and escaped quotes) are: + * + * 1 A double quotation mark preceded by a backslash, \", is interpreted as a + * literal double quotation mark ("). + * + * 2 Backslashes are interpreted literally, unless they immediately precede a + * double quotation mark. + * + * 3 If an even number of backslashes is followed by a double quotation mark, + * then one backslash (\) is placed in the argv array for every pair of + * backslashes (\\), and the double quotation mark (") is interpreted as a + * string delimiter. + * + * 4 If an odd number of backslashes is followed by a double quotation mark, + * then one backslash (\) is placed in the argv array for every pair of + * backslashes (\\) and the double quotation mark is interpreted as an + * escape sequence by the remaining backslash, causing a literal double + * quotation mark (") to be placed in argv. + */ +static char* +unquote(const char *s) { + const char *p = s; /* Pointer to the tail of the original string */ + char *un = (char*)JLI_MemAlloc(strlen(s) + 1); /* Ptr to unquoted string */ + char *pun = un; /* Pointer to the tail of the unquoted string */ + + while (*p != '\0') { + if (*p == '"') { + p++; + } else if (*p == '\\') { + const char *q = p + strspn(p,"\\"); + if (*q == '"') + do { + *pun++ = '\\'; + p += 2; + } while (*p == '\\' && p < q); + else + while (p < q) + *pun++ = *p++; + } else { + *pun++ = *p++; + } + } + *pun = '\0'; + return un; +} + +/* + * Given a path to a jre to execute, this routine checks if this process + * is indeed that jre. If not, it exec's that jre. + * + * We want to actually check the paths rather than just the version string + * built into the executable, so that given version specification will yield + * the exact same Java environment, regardless of the version of the arbitrary + * launcher we start with. + */ +void +ExecJRE(char *jre, char **argv) { + int len; + char *progname; + char path[MAXPATHLEN + 1]; + + /* + * Determine the executable we are building (or in the rare case, running). + */ +#ifdef JAVA_ARGS /* javac, jar and friends. */ + progname = "java"; +#else /* java, oldjava, javaw and friends */ +#ifdef PROGNAME + progname = PROGNAME; +#else + { + char *s; + progname = *argv; + if ((s = strrchr(progname, FILE_SEPARATOR)) != 0) { + progname = s + 1; + } + } +#endif /* PROGNAME */ +#endif /* JAVA_ARGS */ + + /* + * Resolve the real path to the currently running launcher. + */ + len = GetModuleFileName(NULL, path, MAXPATHLEN + 1); + if (len == 0 || len > MAXPATHLEN) { + ReportSysErrorMessage2( + "Unable to resolve path to current %s executable: %s", + progname, JNI_TRUE); + exit(1); + } + + if (_launcher_debug) { + printf("ExecJRE: old: %s\n", path); + printf("ExecJRE: new: %s\n", jre); + } + + /* + * If the path to the selected JRE directory is a match to the initial + * portion of the path to the currently executing JRE, we have a winner! + * If so, just return. (strnicmp() is the Windows equiv. of strncasecmp().) + */ + if (strnicmp(jre, path, strlen(jre)) == 0) + return; /* I am the droid you were looking for */ + + /* + * If this isn't the selected version, exec the selected version. + */ + (void)strcat(strcat(strcpy(path, jre), "\\bin\\"), progname); + (void)strcat(path, ".exe"); + + /* + * Although Windows has an execv() entrypoint, it doesn't actually + * overlay a process: it can only create a new process and terminate + * the old process. Therefore, any processes waiting on the initial + * process wake up and they shouldn't. Hence, a chain of pseudo-zombie + * processes must be retained to maintain the proper wait semantics. + * Fortunately the image size of the launcher isn't too large at this + * time. + * + * If it weren't for this semantic flaw, the code below would be ... + * + * execv(path, argv); + * ReportErrorMessage2("Exec of %s failed\n", path, JNI_TRUE); + * exit(1); + * + * The incorrect exec semantics could be addressed by: + * + * exit((int)spawnv(_P_WAIT, path, argv)); + * + * Unfortunately, a bug in Windows spawn/exec impementation prevents + * this from completely working. All the Windows POSIX process creation + * interfaces are implemented as wrappers around the native Windows + * function CreateProcess(). CreateProcess() takes a single string + * to specify command line options and arguments, so the POSIX routine + * wrappers build a single string from the argv[] array and in the + * process, any quoting information is lost. + * + * The solution to this to get the original command line, to process it + * to remove the new multiple JRE options (if any) as was done for argv + * in the common SelectVersion() routine and finally to pass it directly + * to the native CreateProcess() Windows process control interface. + */ + { + char *cmdline; + char *p; + char *np; + char *ocl; + char *ccl; + char *unquoted; + DWORD exitCode; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + /* + * The following code block gets and processes the original command + * line, replacing the argv[0] equivalent in the command line with + * the path to the new executable and removing the appropriate + * Multiple JRE support options. Note that similar logic exists + * in the platform independent SelectVersion routine, but is + * replicated here due to the syntax of CreateProcess(). + * + * The magic "+ 4" characters added to the command line length are + * 2 possible quotes around the path (argv[0]), a space after the + * path and a terminating null character. + */ + ocl = GetCommandLine(); + np = ccl = JLI_StringDup(ocl); + p = nextarg(&np); /* Discard argv[0] */ + cmdline = (char *)JLI_MemAlloc(strlen(path) + strlen(np) + 4); + if (strchr(path, (int)' ') == NULL && strchr(path, (int)'\t') == NULL) + cmdline = strcpy(cmdline, path); + else + cmdline = strcat(strcat(strcpy(cmdline, "\""), path), "\""); + + while (*np != (char)0) { /* While more command-line */ + p = nextarg(&np); + if (*p != (char)0) { /* If a token was isolated */ + unquoted = unquote(p); + if (*unquoted == '-') { /* Looks like an option */ + if (strcmp(unquoted, "-classpath") == 0 || + strcmp(unquoted, "-cp") == 0) { /* Unique cp syntax */ + cmdline = strcat(strcat(cmdline, " "), p); + p = nextarg(&np); + if (*p != (char)0) /* If a token was isolated */ + cmdline = strcat(strcat(cmdline, " "), p); + } else if (strncmp(unquoted, "-version:", 9) != 0 && + strcmp(unquoted, "-jre-restrict-search") != 0 && + strcmp(unquoted, "-no-jre-restrict-search") != 0) { + cmdline = strcat(strcat(cmdline, " "), p); + } + } else { /* End of options */ + cmdline = strcat(strcat(cmdline, " "), p); + cmdline = strcat(strcat(cmdline, " "), np); + JLI_MemFree((void *)unquoted); + break; + } + JLI_MemFree((void *)unquoted); + } + } + JLI_MemFree((void *)ccl); + + if (_launcher_debug) { + np = ccl = JLI_StringDup(cmdline); + p = nextarg(&np); + printf("ReExec Command: %s (%s)\n", path, p); + printf("ReExec Args: %s\n", np); + JLI_MemFree((void *)ccl); + } + (void)fflush(stdout); + (void)fflush(stderr); + + /* + * The following code is modeled after a model presented in the + * Microsoft Technical Article "Moving Unix Applications to + * Windows NT" (March 6, 1994) and "Creating Processes" on MSDN + * (Februrary 2005). It approximates UNIX spawn semantics with + * the parent waiting for termination of the child. + */ + memset(&si, 0, sizeof(si)); + si.cb =sizeof(STARTUPINFO); + memset(&pi, 0, sizeof(pi)); + + if (!CreateProcess((LPCTSTR)path, /* executable name */ + (LPTSTR)cmdline, /* command line */ + (LPSECURITY_ATTRIBUTES)NULL, /* process security attr. */ + (LPSECURITY_ATTRIBUTES)NULL, /* thread security attr. */ + (BOOL)TRUE, /* inherits system handles */ + (DWORD)0, /* creation flags */ + (LPVOID)NULL, /* environment block */ + (LPCTSTR)NULL, /* current directory */ + (LPSTARTUPINFO)&si, /* (in) startup information */ + (LPPROCESS_INFORMATION)&pi)) { /* (out) process information */ + ReportSysErrorMessage2("CreateProcess(%s, ...) failed: %s", + path, JNI_TRUE); + exit(1); + } + + if (WaitForSingleObject(pi.hProcess, INFINITE) != WAIT_FAILED) { + if (GetExitCodeProcess(pi.hProcess, &exitCode) == FALSE) + exitCode = 1; + } else { + ReportErrorMessage("WaitForSingleObject() failed.", JNI_TRUE); + exitCode = 1; + } + + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + + exit(exitCode); + } + +} + +#endif /* ifndef GAMMA */ + + +/* + * Wrapper for platform dependent unsetenv function. + */ +int +UnsetEnv(char *name) +{ + int ret; + char *buf = JLI_MemAlloc(strlen(name) + 2); + buf = strcat(strcpy(buf, name), "="); + ret = _putenv(buf); + JLI_MemFree(buf); + return (ret); +} + +/* --- Splash Screen shared library support --- */ + +static const char* SPLASHSCREEN_SO = "\\bin\\splashscreen.dll"; + +static HMODULE hSplashLib = NULL; + +void* SplashProcAddress(const char* name) { + char libraryPath[MAXPATHLEN]; /* some extra space for strcat'ing SPLASHSCREEN_SO */ + + if (!GetJREPath(libraryPath, MAXPATHLEN)) { + return NULL; + } + if (strlen(libraryPath)+strlen(SPLASHSCREEN_SO) >= MAXPATHLEN) { + return NULL; + } + strcat(libraryPath, SPLASHSCREEN_SO); + + if (!hSplashLib) { + hSplashLib = LoadLibrary(libraryPath); + } + if (hSplashLib) { + return GetProcAddress(hSplashLib, name); + } else { + return NULL; + } +} + +void SplashFreeLibrary() { + if (hSplashLib) { + FreeLibrary(hSplashLib); + hSplashLib = NULL; + } +} + +const char * +jlong_format_specifier() { + return "%I64d"; +} + +/* + * Block current thread and continue execution in a new thread + */ +int +ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) { + int rslt = 0; + unsigned thread_id; + +#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION +#define STACK_SIZE_PARAM_IS_A_RESERVATION (0x10000) +#endif + + /* + * STACK_SIZE_PARAM_IS_A_RESERVATION is what we want, but it's not + * supported on older version of Windows. Try first with the flag; and + * if that fails try again without the flag. See MSDN document or HotSpot + * source (os_win32.cpp) for details. + */ + HANDLE thread_handle = + (HANDLE)_beginthreadex(NULL, + (unsigned)stack_size, + continuation, + args, + STACK_SIZE_PARAM_IS_A_RESERVATION, + &thread_id); + if (thread_handle == NULL) { + thread_handle = + (HANDLE)_beginthreadex(NULL, + (unsigned)stack_size, + continuation, + args, + 0, + &thread_id); + } + + /* AWT preloading (AFTER main thread start) */ +#ifdef ENABLE_AWT_PRELOAD + /* D3D preloading */ + if (awtPreloadD3D != 0) { + char *envValue; + /* D3D routines checks env.var J2D_D3D if no appropriate + * command line params was specified + */ + envValue = getenv("J2D_D3D"); + if (envValue != NULL && stricmp(envValue, "false") == 0) { + awtPreloadD3D = 0; + } + /* Test that AWT preloading isn't disabled by J2D_D3D_PRELOAD env.var */ + envValue = getenv("J2D_D3D_PRELOAD"); + if (envValue != NULL && stricmp(envValue, "false") == 0) { + awtPreloadD3D = 0; + } + if (awtPreloadD3D < 0) { + /* If awtPreloadD3D is still undefined (-1), test + * if it is turned on by J2D_D3D_PRELOAD env.var. + * By default it's turned OFF. + */ + awtPreloadD3D = 0; + if (envValue != NULL && stricmp(envValue, "true") == 0) { + awtPreloadD3D = 1; + } + } + } + if (awtPreloadD3D) { + AWTPreload(D3D_PRELOAD_FUNC); + } +#endif /* ENABLE_AWT_PRELOAD */ + + if (thread_handle) { + WaitForSingleObject(thread_handle, INFINITE); + GetExitCodeThread(thread_handle, &rslt); + CloseHandle(thread_handle); + } else { + rslt = continuation(args); + } + +#ifdef ENABLE_AWT_PRELOAD + if (awtPreloaded) { + AWTPreloadStop(); + } +#endif /* ENABLE_AWT_PRELOAD */ + + return rslt; +} + +/* Linux only, empty on windows. */ +void SetJavaLauncherPlatformProps() {} + + +//============================== +// AWT preloading +#ifdef ENABLE_AWT_PRELOAD + +typedef int FnPreloadStart(void); +typedef void FnPreloadStop(void); +static FnPreloadStop *fnPreloadStop = NULL; +static HMODULE hPreloadAwt = NULL; + +/* + * Starts AWT preloading + */ +int AWTPreload(const char *funcName) +{ + int result = -1; + + // load AWT library once (if several preload function should be called) + if (hPreloadAwt == NULL) { + // awt.dll is not loaded yet + char libraryPath[MAXPATHLEN]; + int jrePathLen = 0; + HMODULE hJava = NULL; + HMODULE hVerify = NULL; + + while (1) { + // awt.dll depends on jvm.dll & java.dll; + // jvm.dll is already loaded, so we need only java.dll; + // java.dll depends on MSVCRT lib & verify.dll. + if (!GetJREPath(libraryPath, MAXPATHLEN)) { + break; + } + + // save path length + jrePathLen = strlen(libraryPath); + + // load msvcrt 1st + LoadMSVCRT(); + + // load verify.dll + strcat(libraryPath, "\\bin\\verify.dll"); + hVerify = LoadLibrary(libraryPath); + if (hVerify == NULL) { + break; + } + + // restore jrePath + libraryPath[jrePathLen] = 0; + // load java.dll + strcat(libraryPath, "\\bin\\" JAVA_DLL); + hJava = LoadLibrary(libraryPath); + if (hJava == NULL) { + break; + } + + // restore jrePath + libraryPath[jrePathLen] = 0; + // load awt.dll + strcat(libraryPath, "\\bin\\awt.dll"); + hPreloadAwt = LoadLibrary(libraryPath); + if (hPreloadAwt == NULL) { + break; + } + + // get "preloadStop" func ptr + fnPreloadStop = (FnPreloadStop *)GetProcAddress(hPreloadAwt, "preloadStop"); + + break; + } + } + + if (hPreloadAwt != NULL) { + FnPreloadStart *fnInit = (FnPreloadStart *)GetProcAddress(hPreloadAwt, funcName); + if (fnInit != NULL) { + // don't forget to stop preloading + awtPreloaded = 1; + + result = fnInit(); + } + } + + return result; +} + +/* + * Terminates AWT preloading + */ +void AWTPreloadStop() { + if (fnPreloadStop != NULL) { + fnPreloadStop(); + } +} + +#endif /* ENABLE_AWT_PRELOAD */ diff --git a/src/os/solaris/launcher/java_md.h b/src/os/windows/launcher/java_md.h similarity index 66% rename from src/os/solaris/launcher/java_md.h rename to src/os/windows/launcher/java_md.h index f9cf34857473b506a4f574bea6f1a810ffb2b0d3..111be1ee13a4d538421c602b0b79f813bd135694 100644 --- a/src/os/solaris/launcher/java_md.h +++ b/src/os/windows/launcher/java_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,28 +22,31 @@ * */ -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ - #ifndef JAVA_MD_H #define JAVA_MD_H -#include -#include -#include +#include +#include +#include #ifndef GAMMA #include "manifest_info.h" #endif +#include "jli_util.h" -#define PATH_SEPARATOR ':' -#define FILESEP "/" -#define FILE_SEPARATOR '/' -#ifndef MAXNAMELEN -#define MAXNAMELEN PATH_MAX +#ifdef GAMMA +#define stricmp _stricmp +#define strnicmp _strnicmp +#define snprintf _snprintf +#define strdup _strdup #endif +#define PATH_SEPARATOR ';' +#define FILESEP "\\" +#define FILE_SEPARATOR '\\' +#define IS_FILE_SEPARATOR(c) ((c) == '\\' || (c) == '/') +#define MAXPATHLEN MAX_PATH +#define MAXNAMELEN MAX_PATH + #ifdef JAVA_ARGS /* * ApplicationHome is prepended to each of these entries; the resulting @@ -51,27 +54,26 @@ * value of -cp option to the launcher. */ #ifndef APP_CLASSPATH -#define APP_CLASSPATH { "/lib/tools.jar", "/classes" } +#define APP_CLASSPATH { "\\lib\\tools.jar", "\\classes" } #endif #endif -#ifdef HAVE_GETHRTIME /* * Support for doing cheap, accurate interval timing. */ -#include -#define CounterGet() (gethrtime()/1000) -#define Counter2Micros(counts) (counts) -#else -#define CounterGet() (0) -#define Counter2Micros(counts) (1) -#endif /* HAVE_GETHRTIME */ +extern jlong CounterGet(void); +extern jlong Counter2Micros(jlong counts); + +#ifdef JAVAW +#define main _main +extern int _main(int argc, char **argv); +#endif /* * Function prototypes. */ #ifndef GAMMA -char *LocateJRE(manifest_info* info); +char *LocateJRE(manifest_info *info); void ExecJRE(char *jre, char **argv); #endif int UnsetEnv(char *name); diff --git a/src/os/windows/vm/hpi_windows.cpp b/src/os/windows/vm/hpi_windows.cpp deleted file mode 100644 index b743849e2dc73999e207f6ace99940d823db50d3..0000000000000000000000000000000000000000 --- a/src/os/windows/vm/hpi_windows.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/hpi.hpp" -#include "runtime/os.hpp" - -typedef jint (JNICALL *init_t)(GetInterfaceFunc *, void *); - -void hpi::initialize_get_interface(vm_calls_t *callbacks) -{ - // Build name of HPI. - char lib_name[JVM_MAXPATHLEN]; - - if (HPILibPath && HPILibPath[0]) { - strncpy(lib_name, HPILibPath, JVM_MAXPATHLEN - 1); - lib_name[JVM_MAXPATHLEN - 1] = '\0'; - } else { - os::jvm_path(lib_name, sizeof lib_name); - -#ifdef PRODUCT - const char *hpi_lib = "\\hpi.dll"; -#else - char *ptr = strrchr(lib_name, '\\'); - // On Win98 GetModuleFileName() returns the path in the upper case. - assert(_strnicmp(ptr, "\\jvm",4) == 0, "invalid library name"); - const char *hpi_lib = (_strnicmp(ptr, "\\jvm_g",6) == 0) ? "\\hpi_g.dll" : "\\hpi.dll"; -#endif - - *(::strrchr(lib_name, '\\')) = '\0'; /* get rid of "\\jvm.dll" */ - char *p = ::strrchr(lib_name, '\\'); - if (p != NULL) *p = '\0'; /* get rid of "\\hotspot" */ - strcat(lib_name, hpi_lib); - } - - // Load it. - if (TraceHPI) tty->print_cr("Loading HPI %s ", lib_name); - HINSTANCE lib_handle = LoadLibrary(lib_name); - if (lib_handle == NULL) { - if (TraceHPI) tty->print_cr("LoadLibrary failed, code = %d", GetLastError()); - return; - } - - // Find hpi initializer. - init_t initer = (init_t)GetProcAddress(lib_handle, "DLL_Initialize"); - if (initer == NULL) { - if (TraceHPI) tty->print_cr("GetProcAddress failed, errcode = %d", GetLastError()); - return; - } - - // Call initializer. - jint init_result = (*initer)(&_get_interface, callbacks); - if (init_result < 0) { - if (TraceHPI) tty->print_cr("DLL_Initialize failed, returned %ld", init_result); - return; - } - - if (TraceHPI) tty->print_cr("success"); - return; -} diff --git a/src/os/windows/vm/hpi_windows.hpp b/src/os/windows/vm/hpi_windows.hpp deleted file mode 100644 index b262c75a32013e56a5c5e0870f7c019db1e368fe..0000000000000000000000000000000000000000 --- a/src/os/windows/vm/hpi_windows.hpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please 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 OS_WINDOWS_VM_HPI_WINDOWS_HPP -#define OS_WINDOWS_VM_HPI_WINDOWS_HPP - -// Win32 delegates these to the HPI. Solaris provides its own -// implementation without using the HPI (for Interrupitble I/O). - -// HPI_FileInterface - -HPIDECL(close, "close", _file, Close, int, "%d", - (int fd), - ("fd = %d", fd), - (fd)); - -HPIDECL(read, "read", _file, Read, size_t, "%ld", - (int fd, void *buf, unsigned int nBytes), - ("fd = %d, buf = %p, nBytes = %u", fd, buf, nBytes), - (fd, buf, nBytes)); - -HPIDECL(write, "write", _file, Write, size_t, "%ld", - (int fd, const void *buf, unsigned int nBytes), - ("fd = %d, buf = %p, nBytes = %u", fd, buf, nBytes), - (fd, buf, nBytes)); - - -// HPI_SocketInterface - -HPIDECL(socket_close, "socket_close", _socket, Close, int, "%d", - (int fd), - ("fd = %d", fd), - (fd)); - -HPIDECL(socket_available, "socket_available", _socket, Available, - int, "%d", - (int fd, jint *pbytes), - ("fd = %d, pbytes = %p", fd, pbytes), - (fd, pbytes)); - -HPIDECL(socket, "socket", _socket, Socket, int, "%d", - (int domain, int type, int protocol), - ("domain = %d, type = %d, protocol = %d", domain, type, protocol), - (domain, type, protocol)); - -HPIDECL(listen, "listen", _socket, Listen, int, "%d", - (int fd, int count), - ("fd = %d, count = %d", fd, count), - (fd, count)); - -HPIDECL(connect, "connect", _socket, Connect, int, "%d", - (int fd, struct sockaddr *him, int len), - ("fd = %d, him = %p, len = %d", fd, him, len), - (fd, him, len)); - -HPIDECL(accept, "accept", _socket, Accept, int, "%d", - (int fd, struct sockaddr *him, int *len), - ("fd = %d, him = %p, len = %p", fd, him, len), - (fd, him, len)); - -HPIDECL(sendto, "sendto", _socket, SendTo, int, "%d", - (int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen), - ("fd = %d, buf = %p, len = %d, flags = %d, to = %p, tolen = %d", - fd, buf, len, flags, to, tolen), - (fd, buf, len, flags, to, tolen)); - -HPIDECL(recvfrom, "recvfrom", _socket, RecvFrom, int, "%d", - (int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen), - ("fd = %d, buf = %p, len = %d, flags = %d, frm = %p, frmlen = %d", - fd, buf, nbytes, flags, from, fromlen), - (fd, buf, nbytes, flags, from, fromlen)); - -HPIDECL(recv, "recv", _socket, Recv, int, "%d", - (int fd, char *buf, int nBytes, int flags), - ("fd = %d, buf = %p, nBytes = %d, flags = %d", - fd, buf, nBytes, flags), - (fd, buf, nBytes, flags)); - -HPIDECL(send, "send", _socket, Send, int, "%d", - (int fd, char *buf, int nBytes, int flags), - ("fd = %d, buf = %p, nBytes = %d, flags = %d", - fd, buf, nBytes, flags), - (fd, buf, nBytes, flags)); - -inline int hpi::raw_send(int fd, char *buf, int nBytes, int flags) { - return send(fd, buf, nBytes, flags); -} - -HPIDECL(timeout, "timeout", _socket, Timeout, int, "%d", - (int fd, long timeout), - ("fd = %d, timeout = %ld", fd, timeout), - (fd, timeout)); - -HPIDECL(get_host_by_name, "get_host_by_name", _socket, GetHostByName, - struct hostent *, "(struct hostent *)%p", - (char *name), - ("%s", name), - (name)); - -HPIDECL(socket_shutdown, "socket_shutdown", _socket, SocketShutdown, - int, "%d", - (int fd, int howto), - ("fd = %d, howto = %d", fd, howto), - (fd, howto)); - -HPIDECL(bind, "bind", _socket, Bind, - int, "%d", - (int fd, struct sockaddr *him, int len), - ("fd = %d, him = %p, len = %d", - fd, him, len), - (fd, him, len)); - -HPIDECL(get_sock_name, "get_sock_name", _socket, GetSocketName, - int, "%d", - (int fd, struct sockaddr *him, int *len), - ("fd = %d, him = %p, len = %p", - fd, him, len), - (fd, him, len)); - -HPIDECL(get_host_name, "get_host_name", _socket, GetHostName, int, "%d", - (char *hostname, int namelen), - ("hostname = %p, namelen = %d", - hostname, namelen), - (hostname, namelen)); - -HPIDECL(get_host_by_addr, "get_host_by_addr", _socket, GetHostByAddr, - struct hostent *, "(struct hostent *)%p", - (const char* name, int len, int type), - ("name = %p, len = %d, type = %d", - name, len, type), - (name, len, type)); - -HPIDECL(get_sock_opt, "get_sock_opt", _socket, SocketGetOption, int, "%d", - (int fd, int level, int optname, char *optval, int* optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %p", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - -HPIDECL(set_sock_opt, "set_sock_opt", _socket, SocketSetOption, int, "%d", - (int fd, int level, int optname, const char *optval, int optlen), - ("fd = %d, level = %d, optname = %d, optval = %p, optlen = %d", - fd, level, optname, optval, optlen), - (fd, level, optname, optval, optlen)); - -HPIDECL(get_proto_by_name, "get_proto_by_name", _socket, GetProtoByName, - struct protoent *, "(struct protoent *)%p", - (char* name), - ("name = %p", - name), - (name)); - -#endif // OS_WINDOWS_VM_HPI_WINDOWS_HPP diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp index d5d9a6ceef2db0a35fec46ac990397e35d10546d..fe9ed10cace0c6674cb61256922c68ec474138f6 100644 --- a/src/os/windows/vm/os_windows.cpp +++ b/src/os/windows/vm/os_windows.cpp @@ -47,7 +47,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/globals.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -1044,8 +1043,6 @@ os::closedir(DIR *dirp) return 0; } -const char* os::dll_file_extension() { return ".dll"; } - const char* os::get_temp_directory() { const char *prop = Arguments::get_property("java.io.tmpdir"); if (prop != 0) return prop; @@ -1067,7 +1064,6 @@ static bool file_exists(const char* filename) { void os::dll_build_name(char *buffer, size_t buflen, const char* pname, const char* fname) { - // Copied from libhpi const size_t pnamelen = pname ? strlen(pname) : 0; const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0; @@ -1378,10 +1374,6 @@ bool os::dll_address_to_function_name(address addr, char *buf, return false; } -void* os::dll_lookup(void* handle, const char* name) { - return GetProcAddress((HMODULE)handle, name); -} - // save the start and end address of jvm.dll into param[0] and param[1] static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr, unsigned size, void * param) { @@ -1716,7 +1708,37 @@ void os::jvm_path(char *buf, jint buflen) { return; } + buf[0] = '\0'; + if (strcmp(Arguments::sun_java_launcher(), "gamma") == 0) { + // Support for the gamma launcher. Check for an + // ALT_JAVA_HOME or JAVA_HOME environment variable + // and fix up the path so it looks like + // libjvm.so is installed there (append a fake suffix + // hotspot/libjvm.so). + char* java_home_var = ::getenv("ALT_JAVA_HOME"); + if (java_home_var == NULL) { + java_home_var = ::getenv("JAVA_HOME"); + } + if (java_home_var != NULL && java_home_var[0] != 0) { + + strncpy(buf, java_home_var, buflen); + + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + size_t len = strlen(buf); + char* jrebin_p = buf + len; + jio_snprintf(jrebin_p, buflen-len, "\\jre\\bin\\"); + if (0 != _access(buf, 0)) { + jio_snprintf(jrebin_p, buflen-len, "\\bin\\"); + } + len = strlen(buf); + jio_snprintf(buf + len, buflen-len, "hotspot\\jvm.dll"); + } + } + + if(buf[0] == '\0') { GetModuleFileName(vm_lib_handle, buf, buflen); + } strcpy(saved_jvm_path, buf); } @@ -1734,6 +1756,44 @@ void os::print_jni_name_suffix_on(outputStream* st, int args_size) { #endif } +// This method is a copy of JDK's sysGetLastErrorString +// from src/windows/hpi/src/system_md.c + +size_t os::lasterror(char *buf, size_t len) { + long errval; + + if ((errval = GetLastError()) != 0) { + /* DOS error */ + int n = (int)FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + errval, + 0, + buf, + (DWORD)len, + NULL); + if (n > 3) { + /* Drop final '.', CR, LF */ + if (buf[n - 1] == '\n') n--; + if (buf[n - 1] == '\r') n--; + if (buf[n - 1] == '.') n--; + buf[n] = '\0'; + } + return n; + } + + if (errno != 0) { + /* C runtime error that has no corresponding DOS error code */ + const char *s = strerror(errno); + size_t n = strlen(s); + if (n >= len) n = len - 1; + strncpy(buf, s, n); + buf[n] = '\0'; + return n; + } + return 0; +} + // sun.misc.Signal // NOTE that this is a workaround for an apparent kernel bug where if // a signal handler for SIGBREAK is installed then that signal handler @@ -2941,10 +3001,6 @@ void os::pd_start_thread(Thread* thread) { assert(ret != SYS_THREAD_ERROR, "StartThread failed"); // should propagate back } -size_t os::read(int fd, void *buf, unsigned int nBytes) { - return ::read(fd, buf, nBytes); -} - class HighResolutionInterval { // The default timer resolution seems to be 10 milliseconds. // (Where is this written down?) @@ -3423,10 +3479,6 @@ jint os::init_2(void) { #endif } - // Initialize HPI. - jint hpi_result = hpi::initialize(); - if (hpi_result != JNI_OK) { return hpi_result; } - // If stack_commit_size is 0, windows will reserve the default size, // but only commit a small portion of it. size_t stack_commit_size = round_to(ThreadStackSize*K, os::vm_page_size()); @@ -3531,7 +3583,7 @@ int os::stat(const char *path, struct stat *sbuf) { errno = ENAMETOOLONG; return -1; } - hpi::native_path(strcpy(pathbuf, path)); + os::native_path(strcpy(pathbuf, path)); int ret = ::stat(pathbuf, sbuf); if (sbuf != NULL && UseUTCFileTimestamp) { // Fix for 6539723. st_mtime returned from stat() is dependent on @@ -3675,6 +3727,20 @@ bool os::dont_yield() { return DontYieldALot; } +// This method is a slightly reworked copy of JDK's sysOpen +// from src/windows/hpi/src/sys_api_md.c + +int os::open(const char *path, int oflag, int mode) { + char pathbuf[MAX_PATH]; + + if (strlen(path) > MAX_PATH - 1) { + errno = ENAMETOOLONG; + return -1; + } + os::native_path(strcpy(pathbuf, path)); + return ::open(pathbuf, oflag | O_BINARY | O_NOINHERIT, mode); +} + // Is a (classpath) directory empty? bool os::dir_is_empty(const char* path) { WIN32_FIND_DATA fd; @@ -3706,6 +3772,297 @@ jlong os::seek_to_file_offset(int fd, jlong offset) { } +jlong os::lseek(int fd, jlong offset, int whence) { + return (jlong) ::_lseeki64(fd, offset, whence); +} + +// This method is a slightly reworked copy of JDK's sysNativePath +// from src/windows/hpi/src/path_md.c + +/* Convert a pathname to native format. On win32, this involves forcing all + separators to be '\\' rather than '/' (both are legal inputs, but Win95 + sometimes rejects '/') and removing redundant separators. The input path is + assumed to have been converted into the character encoding used by the local + system. Because this might be a double-byte encoding, care is taken to + treat double-byte lead characters correctly. + + This procedure modifies the given path in place, as the result is never + longer than the original. There is no error return; this operation always + succeeds. */ +char * os::native_path(char *path) { + char *src = path, *dst = path, *end = path; + char *colon = NULL; /* If a drive specifier is found, this will + point to the colon following the drive + letter */ + + /* Assumption: '/', '\\', ':', and drive letters are never lead bytes */ + assert(((!::IsDBCSLeadByte('/')) + && (!::IsDBCSLeadByte('\\')) + && (!::IsDBCSLeadByte(':'))), + "Illegal lead byte"); + + /* Check for leading separators */ +#define isfilesep(c) ((c) == '/' || (c) == '\\') + while (isfilesep(*src)) { + src++; + } + + if (::isalpha(*src) && !::IsDBCSLeadByte(*src) && src[1] == ':') { + /* Remove leading separators if followed by drive specifier. This + hack is necessary to support file URLs containing drive + specifiers (e.g., "file://c:/path"). As a side effect, + "/c:/path" can be used as an alternative to "c:/path". */ + *dst++ = *src++; + colon = dst; + *dst++ = ':'; + src++; + } else { + src = path; + if (isfilesep(src[0]) && isfilesep(src[1])) { + /* UNC pathname: Retain first separator; leave src pointed at + second separator so that further separators will be collapsed + into the second separator. The result will be a pathname + beginning with "\\\\" followed (most likely) by a host name. */ + src = dst = path + 1; + path[0] = '\\'; /* Force first separator to '\\' */ + } + } + + end = dst; + + /* Remove redundant separators from remainder of path, forcing all + separators to be '\\' rather than '/'. Also, single byte space + characters are removed from the end of the path because those + are not legal ending characters on this operating system. + */ + while (*src != '\0') { + if (isfilesep(*src)) { + *dst++ = '\\'; src++; + while (isfilesep(*src)) src++; + if (*src == '\0') { + /* Check for trailing separator */ + end = dst; + if (colon == dst - 2) break; /* "z:\\" */ + if (dst == path + 1) break; /* "\\" */ + if (dst == path + 2 && isfilesep(path[0])) { + /* "\\\\" is not collapsed to "\\" because "\\\\" marks the + beginning of a UNC pathname. Even though it is not, by + itself, a valid UNC pathname, we leave it as is in order + to be consistent with the path canonicalizer as well + as the win32 APIs, which treat this case as an invalid + UNC pathname rather than as an alias for the root + directory of the current drive. */ + break; + } + end = --dst; /* Path does not denote a root directory, so + remove trailing separator */ + break; + } + end = dst; + } else { + if (::IsDBCSLeadByte(*src)) { /* Copy a double-byte character */ + *dst++ = *src++; + if (*src) *dst++ = *src++; + end = dst; + } else { /* Copy a single-byte character */ + char c = *src++; + *dst++ = c; + /* Space is not a legal ending character */ + if (c != ' ') end = dst; + } + } + } + + *end = '\0'; + + /* For "z:", add "." to work around a bug in the C runtime library */ + if (colon == dst - 1) { + path[2] = '.'; + path[3] = '\0'; + } + + #ifdef DEBUG + jio_fprintf(stderr, "sysNativePath: %s\n", path); + #endif DEBUG + return path; +} + +// This code is a copy of JDK's sysSetLength +// from src/windows/hpi/src/sys_api_md.c + +int os::ftruncate(int fd, jlong length) { + HANDLE h = (HANDLE)::_get_osfhandle(fd); + long high = (long)(length >> 32); + DWORD ret; + + if (h == (HANDLE)(-1)) { + return -1; + } + + ret = ::SetFilePointer(h, (long)(length), &high, FILE_BEGIN); + if ((ret == 0xFFFFFFFF) && (::GetLastError() != NO_ERROR)) { + return -1; + } + + if (::SetEndOfFile(h) == FALSE) { + return -1; + } + + return 0; +} + + +// This code is a copy of JDK's sysSync +// from src/windows/hpi/src/sys_api_md.c +// except for the legacy workaround for a bug in Win 98 + +int os::fsync(int fd) { + HANDLE handle = (HANDLE)::_get_osfhandle(fd); + + if ( (!::FlushFileBuffers(handle)) && + (GetLastError() != ERROR_ACCESS_DENIED) ) { + /* from winerror.h */ + return -1; + } + return 0; +} + +static int nonSeekAvailable(int, long *); +static int stdinAvailable(int, long *); + +#define S_ISCHR(mode) (((mode) & _S_IFCHR) == _S_IFCHR) +#define S_ISFIFO(mode) (((mode) & _S_IFIFO) == _S_IFIFO) + +// This code is a copy of JDK's sysAvailable +// from src/windows/hpi/src/sys_api_md.c + +int os::available(int fd, jlong *bytes) { + jlong cur, end; + struct _stati64 stbuf64; + + if (::_fstati64(fd, &stbuf64) >= 0) { + int mode = stbuf64.st_mode; + if (S_ISCHR(mode) || S_ISFIFO(mode)) { + int ret; + long lpbytes; + if (fd == 0) { + ret = stdinAvailable(fd, &lpbytes); + } else { + ret = nonSeekAvailable(fd, &lpbytes); + } + (*bytes) = (jlong)(lpbytes); + return ret; + } + if ((cur = ::_lseeki64(fd, 0L, SEEK_CUR)) == -1) { + return FALSE; + } else if ((end = ::_lseeki64(fd, 0L, SEEK_END)) == -1) { + return FALSE; + } else if (::_lseeki64(fd, cur, SEEK_SET) == -1) { + return FALSE; + } + *bytes = end - cur; + return TRUE; + } else { + return FALSE; + } +} + +// This code is a copy of JDK's nonSeekAvailable +// from src/windows/hpi/src/sys_api_md.c + +static int nonSeekAvailable(int fd, long *pbytes) { + /* This is used for available on non-seekable devices + * (like both named and anonymous pipes, such as pipes + * connected to an exec'd process). + * Standard Input is a special case. + * + */ + HANDLE han; + + if ((han = (HANDLE) ::_get_osfhandle(fd)) == (HANDLE)(-1)) { + return FALSE; + } + + if (! ::PeekNamedPipe(han, NULL, 0, NULL, (LPDWORD)pbytes, NULL)) { + /* PeekNamedPipe fails when at EOF. In that case we + * simply make *pbytes = 0 which is consistent with the + * behavior we get on Solaris when an fd is at EOF. + * The only alternative is to raise an Exception, + * which isn't really warranted. + */ + if (::GetLastError() != ERROR_BROKEN_PIPE) { + return FALSE; + } + *pbytes = 0; + } + return TRUE; +} + +#define MAX_INPUT_EVENTS 2000 + +// This code is a copy of JDK's stdinAvailable +// from src/windows/hpi/src/sys_api_md.c + +static int stdinAvailable(int fd, long *pbytes) { + HANDLE han; + DWORD numEventsRead = 0; /* Number of events read from buffer */ + DWORD numEvents = 0; /* Number of events in buffer */ + DWORD i = 0; /* Loop index */ + DWORD curLength = 0; /* Position marker */ + DWORD actualLength = 0; /* Number of bytes readable */ + BOOL error = FALSE; /* Error holder */ + INPUT_RECORD *lpBuffer; /* Pointer to records of input events */ + + if ((han = ::GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) { + return FALSE; + } + + /* Construct an array of input records in the console buffer */ + error = ::GetNumberOfConsoleInputEvents(han, &numEvents); + if (error == 0) { + return nonSeekAvailable(fd, pbytes); + } + + /* lpBuffer must fit into 64K or else PeekConsoleInput fails */ + if (numEvents > MAX_INPUT_EVENTS) { + numEvents = MAX_INPUT_EVENTS; + } + + lpBuffer = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD)); + if (lpBuffer == NULL) { + return FALSE; + } + + error = ::PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead); + if (error == 0) { + os::free(lpBuffer); + return FALSE; + } + + /* Examine input records for the number of bytes available */ + for(i=0; ibKeyDown == TRUE) { + CHAR *keyPressed = (CHAR *) &(keyRecord->uChar); + curLength++; + if (*keyPressed == '\r') { + actualLength = curLength; + } + } + } + } + + if(lpBuffer != NULL) { + os::free(lpBuffer); + } + + *pbytes = (long) actualLength; + return TRUE; +} + // Map a block of memory. char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -3871,7 +4228,7 @@ void os::pause() { int fd = ::open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666); if (fd != -1) { struct stat buf; - close(fd); + ::close(fd); while (::stat(filename, &buf) == 0) { Sleep(100); } @@ -4232,3 +4589,164 @@ static int getLastErrorString(char *buf, size_t len) // We don't build a headless jre for Windows bool os::is_headless_jre() { return false; } +// OS_SocketInterface +// Not used on Windows + +// OS_SocketInterface +typedef struct hostent * (PASCAL FAR *ws2_ifn_ptr_t)(...); +ws2_ifn_ptr_t *get_host_by_name_fn = NULL; + +typedef CRITICAL_SECTION mutex_t; +#define mutexInit(m) InitializeCriticalSection(m) +#define mutexDestroy(m) DeleteCriticalSection(m) +#define mutexLock(m) EnterCriticalSection(m) +#define mutexUnlock(m) LeaveCriticalSection(m) + +static bool sockfnptrs_initialized = FALSE; +static mutex_t sockFnTableMutex; + +/* is Winsock2 loaded? better to be explicit than to rely on sockfnptrs */ +static bool winsock2Available = FALSE; + + +static void initSockFnTable() { + int (PASCAL FAR* WSAStartupPtr)(WORD, LPWSADATA); + WSADATA wsadata; + + ::mutexInit(&sockFnTableMutex); + ::mutexLock(&sockFnTableMutex); + + if (sockfnptrs_initialized == FALSE) { + HMODULE hWinsock; + + /* try to load Winsock2, and if that fails, load Winsock */ + hWinsock = ::LoadLibrary("ws2_32.dll"); + + if (hWinsock == NULL) { + jio_fprintf(stderr, "Could not load Winsock 2 (error: %d)\n", + ::GetLastError()); + return; + } + + /* If we loaded a DLL, then we might as well initialize it. */ + WSAStartupPtr = (int (PASCAL FAR *)(WORD, LPWSADATA)) + ::GetProcAddress(hWinsock, "WSAStartup"); + + if (WSAStartupPtr(MAKEWORD(1,1), &wsadata) != 0) { + jio_fprintf(stderr, "Could not initialize Winsock\n"); + } + + get_host_by_name_fn + = (ws2_ifn_ptr_t*) GetProcAddress(hWinsock, "gethostbyname"); + } + + assert(get_host_by_name_fn != NULL, + "gethostbyname function not found"); + sockfnptrs_initialized = TRUE; + ::mutexUnlock(&sockFnTableMutex); +} + +struct hostent* os::get_host_by_name(char* name) { + if (!sockfnptrs_initialized) { + initSockFnTable(); + } + + assert(sockfnptrs_initialized == TRUE && get_host_by_name_fn != NULL, + "sockfnptrs is not initialized or pointer to gethostbyname function is NULL"); + return (*get_host_by_name_fn)(name); +} + + +int os::socket_close(int fd) { + ShouldNotReachHere(); + return 0; +} + +int os::socket_available(int fd, jint *pbytes) { + ShouldNotReachHere(); + return 0; +} + +int os::socket(int domain, int type, int protocol) { + ShouldNotReachHere(); + return 0; +} + +int os::listen(int fd, int count) { + ShouldNotReachHere(); + return 0; +} + +int os::connect(int fd, struct sockaddr *him, int len) { + ShouldNotReachHere(); + return 0; +} + +int os::accept(int fd, struct sockaddr *him, int *len) { + ShouldNotReachHere(); + return 0; +} + +int os::sendto(int fd, char *buf, int len, int flags, + struct sockaddr *to, int tolen) { + ShouldNotReachHere(); + return 0; +} + +int os::recvfrom(int fd, char *buf, int nBytes, int flags, + sockaddr *from, int *fromlen) { + ShouldNotReachHere(); + return 0; +} + +int os::recv(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::send(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::raw_send(int fd, char *buf, int nBytes, int flags) { + ShouldNotReachHere(); + return 0; +} + +int os::timeout(int fd, long timeout) { + ShouldNotReachHere(); + return 0; +} + +int os::get_host_name(char* name, int namelen) { + ShouldNotReachHere(); + return 0; +} + +int os::socket_shutdown(int fd, int howto) { + ShouldNotReachHere(); + return 0; +} + +int os::bind(int fd, struct sockaddr *him, int len) { + ShouldNotReachHere(); + return 0; +} + +int os::get_sock_name(int fd, struct sockaddr *him, int *len) { + ShouldNotReachHere(); + return 0; +} + +int os::get_sock_opt(int fd, int level, int optname, + char *optval, int* optlen) { + ShouldNotReachHere(); + return 0; +} + +int os::set_sock_opt(int fd, int level, int optname, + const char *optval, int optlen) { + ShouldNotReachHere(); + return 0; +} diff --git a/src/os/windows/vm/os_windows.inline.hpp b/src/os/windows/vm/os_windows.inline.hpp index 20224864ab02bf6ba789b273cabf3199356f3e23..cee281fada7632e3036355d67a1a1673415fe862 100644 --- a/src/os/windows/vm/os_windows.inline.hpp +++ b/src/os/windows/vm/os_windows.inline.hpp @@ -35,15 +35,26 @@ inline const char* os::file_separator() { return "\\"; } inline const char* os::line_separator() { return "\r\n"; } inline const char* os::path_separator() { return ";"; } +inline const char* os::dll_file_extension() { return ".dll"; } inline const char* os::jlong_format_specifier() { return "%I64d"; } inline const char* os::julong_format_specifier() { return "%I64u"; } +inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;} + // File names are case-insensitive on windows only inline int os::file_name_strcmp(const char* s, const char* t) { return _stricmp(s, t); } +inline void os::dll_unload(void *lib) { + ::FreeLibrary((HMODULE)lib); +} + +inline void* os::dll_lookup(void *lib, const char *name) { + return (void*)::GetProcAddress((HMODULE)lib, name); +} + // Used to improve time-sharing on some systems inline void os::loop_breaker(int attempts) {} @@ -83,4 +94,19 @@ inline void os::bang_stack_shadow_pages() { inline bool os::numa_has_static_binding() { return true; } inline bool os::numa_has_group_homing() { return false; } +inline size_t os::read(int fd, void *buf, unsigned int nBytes) { + return ::read(fd, buf, nBytes); +} + +inline size_t os::restartable_read(int fd, void *buf, unsigned int nBytes) { + return ::read(fd, buf, nBytes); +} + +inline size_t os::write(int fd, const void *buf, unsigned int nBytes) { + return ::write(fd, buf, nBytes); +} + +inline int os::close(int fd) { + return ::close(fd); +} #endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP diff --git a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 3a9bb279de94d1493217fcd0abf1821583ae33c3..e759e7d8deae8d9719762b8d06327a83a6350bde 100644 --- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -41,7 +41,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index 22d0b21aaeade423522573a813370ce8487a7cab..f657dfec2d6e217834fa5842a82ff299053ac637 100644 --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -41,7 +41,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index 7a1d216ac70a59374052233ed7ecadbd291d8a81..40e15e2f4f808fa5f8276b0e6f4d954ff385f057 100644 --- a/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -42,7 +42,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index 661c8294ff4087df3bd62a1aa3ec0e9a2b17de26..889f7549f80338363fb64e49c915f3e8eb8e6ef6 100644 --- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -41,7 +41,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" @@ -289,17 +288,17 @@ static int threadgetstate(thread_t tid, int *flags, lwpid_t *lwp, stack_t *ss, g if (*flags == TRS_LWPID) { sprintf(lwpstatusfile, "/proc/%d/lwp/%d/lwpstatus", getpid(), *lwp); - if ((lwpfd = open(lwpstatusfile, O_RDONLY)) < 0) { + if ((lwpfd = ::open(lwpstatusfile, O_RDONLY)) < 0) { perror("thr_mutator_status: open lwpstatus"); return (EINVAL); } if (pread(lwpfd, lwpstatus, sizeof (lwpstatus_t), (off_t)0) != sizeof (lwpstatus_t)) { perror("thr_mutator_status: read lwpstatus"); - (void) close(lwpfd); + (void) ::close(lwpfd); return (EINVAL); } - (void) close(lwpfd); + (void) ::close(lwpfd); } return (0); } diff --git a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 36eb03cd1825721a33810de1db8477d717cfa581..91c7e75a0b4ccdde51c3c8ada452fe7d22cb27b2 100644 --- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -41,7 +41,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index f0d23d9b844c267bc29774dbdf8acc6e3ffa282b..960ceab665ad8fdd3fd483de678ca7a360833059 100644 --- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -41,7 +41,6 @@ #include "runtime/arguments.hpp" #include "runtime/extendedPC.hpp" #include "runtime/frame.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/os/linux/launcher/java.c b/src/share/tools/launcher/java.c similarity index 82% rename from src/os/linux/launcher/java.c rename to src/share/tools/launcher/java.c index 0f69d30112200031754a2458abdf09da8a225fd3..f054be1702ba7577172029d3062f7d3ae4538cfc 100644 --- a/src/os/linux/launcher/java.c +++ b/src/share/tools/launcher/java.c @@ -23,7 +23,7 @@ */ /* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, + * Gamma (Hotspot internal engineering test) launcher based on 6.0u22 JDK, * search "GAMMA" for gamma specific changes. * * GAMMA: gamma launcher is much simpler than regular java launcher in that @@ -62,7 +62,7 @@ * options are turned into "-foo" options to the vm. This option * filtering is handled in a number of places in the launcher, some of * it in machine-dependent code. In this file, the function - * CheckJVMType removes vm style options and TranslateDashJArgs + * CheckJVMType removes vm style options and TranslateApplicationArgs * removes "-J" prefixes. On unix platforms, the * CreateExecutionEnvironment function from the unix java_md.c file * processes and removes -d options. However, in case @@ -79,12 +79,14 @@ #include #include +#include #include "java.h" - #ifndef GAMMA #include "manifest_info.h" #include "version_comp.h" +#include "splashscreen.h" #endif +#include "wildcard.h" #ifndef FULL_VERSION #define FULL_VERSION JDK_MAJOR_VERSION "." JDK_MINOR_VERSION @@ -114,11 +116,27 @@ */ #define ENV_ENTRY "_JAVA_VERSION_SET" +#ifndef GAMMA +#define SPLASH_FILE_ENV_ENTRY "_JAVA_SPLASH_FILE" +#define SPLASH_JAR_ENV_ENTRY "_JAVA_SPLASH_JAR" +#endif + static jboolean printVersion = JNI_FALSE; /* print and exit */ static jboolean showVersion = JNI_FALSE; /* print but continue */ static char *progname; jboolean _launcher_debug = JNI_FALSE; +#ifndef GAMMA +/* + * Entries for splash screen environment variables. + * putenv is performed in SelectVersion. We need + * them in memory until UnsetEnv, so they are made static + * global instead of auto local. + */ +static char* splash_file_entry = NULL; +static char* splash_jar_entry = NULL; +#endif + /* * List of VM options to be specified when the VM is created. */ @@ -128,11 +146,10 @@ static int numOptions, maxOptions; /* * Prototypes for functions internal to launcher. */ -static void AddOption(char *str, void *info); -static void SetClassPath(char *s); +static void SetClassPath(const char *s); static void SelectVersion(int argc, char **argv, char **main_class); static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret); + char **pclassname, int *pret, const char *jvmpath); static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn); static jstring NewPlatformString(JNIEnv *env, char *s); @@ -140,21 +157,21 @@ static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc); static jclass LoadClass(JNIEnv *env, char *name); static jstring GetMainClassName(JNIEnv *env, char *jarname); static void SetJavaCommandLineProp(char* classname, char* jarfile, int argc, char** argv); -#ifdef GAMMA static void SetJavaLauncherProp(void); -#endif #ifdef JAVA_ARGS -static void TranslateDashJArgs(int *pargc, char ***pargv); +static void TranslateApplicationArgs(int *pargc, char ***pargv); static jboolean AddApplicationOptions(void); #endif static void PrintJavaVersion(JNIEnv *env); static void PrintUsage(void); -static jint PrintXUsage(void); +static jint PrintXUsage(const char *jvmpath); static void SetPaths(int argc, char **argv); +#ifndef GAMMA + /* Maximum supported entries from jvm.cfg. */ #define INIT_MAX_KNOWN_VMS 10 /* Values for vmdesc.flag */ @@ -178,41 +195,47 @@ static int knownVMsLimit = 0; static void GrowKnownVMs(); static int KnownVMIndex(const char* name); static void FreeKnownVMs(); +static void ShowSplashScreen(); + +#endif /* ifndef GAMMA */ jboolean ServerClassMachine(); /* flag which if set suppresses error messages from the launcher */ static int noExitErrorMessage = 0; +/* + * Running Java code in primordial thread caused many problems. We will + * create a new thread to invoke JVM. See 6316197 for more information. + */ +static jlong threadStackSize = 0; /* stack size of the new thread */ + +int JNICALL JavaMain(void * args); /* entry point */ + +struct JavaMainArgs { + int argc; + char ** argv; + char * jarfile; + char * classname; + InvocationFunctions ifn; +}; + /* * Entry point. */ int main(int argc, char ** argv) { - JavaVM *vm = 0; - JNIEnv *env = 0; char *jarfile = 0; char *classname = 0; char *s = 0; char *main_class = NULL; - jstring mainClassName; - jclass mainClass; - jmethodID mainID; - jobjectArray mainArgs; int ret; InvocationFunctions ifn; jlong start, end; char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; char ** original_argv = argv; - /* - * Error message to print or display; by default the message will - * only be displayed in a window. - */ - char * message = "Fatal exception occurred. Program will exit."; - jboolean messageDest = JNI_FALSE; - if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) { _launcher_debug = JNI_TRUE; printf("----_JAVA_LAUNCHER_DEBUG----\n"); @@ -242,7 +265,7 @@ main(int argc, char ** argv) /* copy original argv */ { int i; - original_argv = (char**)MemAlloc(sizeof(char*)*(argc+1)); + original_argv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1)); for(i = 0; i < argc+1; i++) original_argv[i] = argv[i]; } @@ -251,6 +274,7 @@ main(int argc, char ** argv) jrepath, sizeof(jrepath), jvmpath, sizeof(jvmpath), original_argv); + ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; @@ -282,7 +306,7 @@ main(int argc, char ** argv) #ifdef JAVA_ARGS /* Preprocess wrapper arguments */ - TranslateDashJArgs(&argc, &argv); + TranslateApplicationArgs(&argc, &argv); if (!AddApplicationOptions()) { exit(1); } @@ -300,7 +324,7 @@ main(int argc, char ** argv) * Parse command line options; if the return value of * ParseArguments is false, the program should exit. */ - if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret)) { + if (!ParseArguments(&argc, &argv, &jarfile, &classname, &ret, jvmpath)) { exit(ret); } @@ -312,9 +336,15 @@ main(int argc, char ** argv) /* set the -Dsun.java.command pseudo property */ SetJavaCommandLineProp(classname, jarfile, argc, argv); -#ifdef GAMMA /* Set the -Dsun.java.launcher pseudo property */ SetJavaLauncherProp(); + + /* set the -Dsun.java.launcher.* platform properties */ + SetJavaLauncherPlatformProps(); + +#ifndef GAMMA + /* Show the splash screen if needed */ + ShowSplashScreen(); #endif /* @@ -322,6 +352,67 @@ main(int argc, char ** argv) * clean up the environment. */ (void)UnsetEnv(ENV_ENTRY); +#ifndef GAMMA + (void)UnsetEnv(SPLASH_FILE_ENV_ENTRY); + (void)UnsetEnv(SPLASH_JAR_ENV_ENTRY); + + JLI_MemFree(splash_jar_entry); + JLI_MemFree(splash_file_entry); +#endif + + /* + * If user doesn't specify stack size, check if VM has a preference. + * Note that HotSpot no longer supports JNI_VERSION_1_1 but it will + * return its default stack size through the init args structure. + */ + if (threadStackSize == 0) { + struct JDK1_1InitArgs args1_1; + memset((void*)&args1_1, 0, sizeof(args1_1)); + args1_1.version = JNI_VERSION_1_1; + ifn.GetDefaultJavaVMInitArgs(&args1_1); /* ignore return value */ + if (args1_1.javaStackSize > 0) { + threadStackSize = args1_1.javaStackSize; + } + } + + { /* Create a new thread to create JVM and invoke main method */ + struct JavaMainArgs args; + + args.argc = argc; + args.argv = argv; + args.jarfile = jarfile; + args.classname = classname; + args.ifn = ifn; + + return ContinueInNewThread(JavaMain, threadStackSize, (void*)&args); + } +} + +int JNICALL +JavaMain(void * _args) +{ + struct JavaMainArgs *args = (struct JavaMainArgs *)_args; + int argc = args->argc; + char **argv = args->argv; + char *jarfile = args->jarfile; + char *classname = args->classname; + InvocationFunctions ifn = args->ifn; + + JavaVM *vm = 0; + JNIEnv *env = 0; + jstring mainClassName; + jclass mainClass; + jmethodID mainID; + jobjectArray mainArgs; + int ret = 0; + jlong start, end; + + /* + * Error message to print or display; by default the message will + * only be displayed in a window. + */ + char * message = "Fatal exception occurred. Program will exit."; + jboolean messageDest = JNI_FALSE; /* Initialize the virtual machine */ @@ -407,7 +498,7 @@ main(int argc, char ** argv) if (mainClassName == NULL) { const char * format = "Failed to load Main-Class manifest " "attribute from\n%s"; - message = (char*)MemAlloc((strlen(format) + strlen(jarfile)) * + message = (char*)JLI_MemAlloc((strlen(format) + strlen(jarfile)) * sizeof(char)); sprintf(message, format, jarfile); messageDest = JNI_TRUE; @@ -419,9 +510,13 @@ main(int argc, char ** argv) goto leave; } mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occurred */ + if(mainClass == NULL) { /* exception occured */ + const char * format = "Could not find the main class: %s. Program will exit."; ReportExceptionDescription(env); - message = "Could not find the main class. Program will exit."; + message = (char *)JLI_MemAlloc((strlen(format) + + strlen(classname)) * sizeof(char) ); + messageDest = JNI_TRUE; + sprintf(message, format, classname); goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); @@ -429,7 +524,7 @@ main(int argc, char ** argv) mainClassName = NewPlatformString(env, classname); if (mainClassName == NULL) { const char * format = "Failed to load Main Class: %s"; - message = (char *)MemAlloc((strlen(format) + strlen(classname)) * + message = (char *)JLI_MemAlloc((strlen(format) + strlen(classname)) * sizeof(char) ); sprintf(message, format, classname); messageDest = JNI_TRUE; @@ -441,9 +536,13 @@ main(int argc, char ** argv) goto leave; } mainClass = LoadClass(env, classname); - if(mainClass == NULL) { /* exception occurred */ + if(mainClass == NULL) { /* exception occured */ + const char * format = "Could not find the main class: %s. Program will exit."; ReportExceptionDescription(env); - message = "Could not find the main class. Program will exit."; + message = (char *)JLI_MemAlloc((strlen(format) + + strlen(classname)) * sizeof(char) ); + messageDest = JNI_TRUE; + sprintf(message, format, classname); goto leave; } (*env)->ReleaseStringUTFChars(env, mainClassName, classname); @@ -538,7 +637,6 @@ main(int argc, char ** argv) return ret; } - #ifndef GAMMA /* * Checks the command line options to find which JVM type was @@ -560,7 +658,7 @@ CheckJvmType(int *pargc, char ***argv, jboolean speculative) { argc = *pargc; /* To make things simpler we always copy the argv array */ - newArgv = MemAlloc((argc + 1) * sizeof(char *)); + newArgv = JLI_MemAlloc((argc + 1) * sizeof(char *)); /* The program name is always present */ newArgv[newArgvIdx++] = (*argv)[0]; @@ -700,10 +798,51 @@ CheckJvmType(int *pargc, char ***argv, jboolean speculative) { } #endif /* ifndef GAMMA */ +# define KB (1024UL) +# define MB (1024UL * KB) +# define GB (1024UL * MB) + +/* copied from HotSpot function "atomll()" */ +static int +parse_stack_size(const char *s, jlong *result) { + jlong n = 0; + int args_read = sscanf(s, jlong_format_specifier(), &n); + if (args_read != 1) { + return 0; + } + while (*s != '\0' && *s >= '0' && *s <= '9') { + s++; + } + // 4705540: illegal if more characters are found after the first non-digit + if (strlen(s) > 1) { + return 0; + } + switch (*s) { + case 'T': case 't': + *result = n * GB * KB; + return 1; + case 'G': case 'g': + *result = n * GB; + return 1; + case 'M': case 'm': + *result = n * MB; + return 1; + case 'K': case 'k': + *result = n * KB; + return 1; + case '\0': + *result = n; + return 1; + default: + /* Create JVM with default stack and let VM handle malformed -Xss string*/ + return 0; + } +} + /* * Adds a new VM option with the given given name and value. */ -static void +void AddOption(char *str, void *info) { /* @@ -713,24 +852,33 @@ AddOption(char *str, void *info) if (numOptions >= maxOptions) { if (options == 0) { maxOptions = 4; - options = MemAlloc(maxOptions * sizeof(JavaVMOption)); + options = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption)); } else { JavaVMOption *tmp; maxOptions *= 2; - tmp = MemAlloc(maxOptions * sizeof(JavaVMOption)); + tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption)); memcpy(tmp, options, numOptions * sizeof(JavaVMOption)); - free(options); + JLI_MemFree(options); options = tmp; } } options[numOptions].optionString = str; options[numOptions++].extraInfo = info; + + if (strncmp(str, "-Xss", 4) == 0) { + jlong tmp; + if (parse_stack_size(str + 4, &tmp)) { + threadStackSize = tmp; + } + } } static void -SetClassPath(char *s) +SetClassPath(const char *s) { - char *def = MemAlloc(strlen(s) + 40); + char *def; + s = JLI_WildcardExpandClasspath(s); + def = JLI_MemAlloc(strlen(s) + 40); sprintf(def, "-Djava.class.path=%s", s); AddOption(def, NULL); } @@ -741,6 +889,8 @@ SetClassPath(char *s) * the JRE is running. The specification for the appropriate version * is obtained from either the manifest of a jar file (preferred) or * from command line options. + * The routine also parses splash screen command line options and + * passes on their values in private environment variables. */ static void SelectVersion(int argc, char **argv, char **main_class) @@ -752,9 +902,12 @@ SelectVersion(int argc, char **argv, char **main_class) char *version = NULL; char *jre = NULL; int jarflag = 0; + int headlessflag = 0; int restrict_search = -1; /* -1 implies not known */ manifest_info info; char env_entry[MAXNAMELEN + 24] = ENV_ENTRY "="; + char *splash_file_name = NULL; + char *splash_jar_name = NULL; char *env_in; int res; @@ -765,7 +918,7 @@ SelectVersion(int argc, char **argv, char **main_class) */ if ((env_in = getenv(ENV_ENTRY)) != NULL) { if (*env_in != '\0') - *main_class = strdup(env_in); + *main_class = JLI_StringDup(env_in); return; } @@ -781,8 +934,13 @@ SelectVersion(int argc, char **argv, char **main_class) * As the scan is performed, make a copy of the argument list with * the version specification options (new to 1.5) removed, so that * a version less than 1.5 can be exec'd. + * + * Note that due to the syntax of the native Windows interface + * CreateProcess(), processing similar to the following exists in + * the Windows platform specific routine ExecJRE (in java_md.c). + * Changes here should be reproduced there. */ - new_argv = MemAlloc((argc + 1) * sizeof(char*)); + new_argv = JLI_MemAlloc((argc + 1) * sizeof(char*)); new_argv[0] = argv[0]; new_argp = &new_argv[1]; argc--; @@ -805,6 +963,18 @@ SelectVersion(int argc, char **argv, char **main_class) argv++; arg = *argv; } + + /* + * Checking for headless toolkit option in the some way as AWT does: + * "true" means true and any other value means false + */ + if (strcmp(arg, "-Djava.awt.headless=true") == 0) { + headlessflag = 1; + } else if (strncmp(arg, "-Djava.awt.headless=", 20) == 0) { + headlessflag = 0; + } else if (strncmp(arg, "-splash:", 8) == 0) { + splash_file_name = arg+8; + } *new_argp++ = arg; } argc--; @@ -830,7 +1000,7 @@ SelectVersion(int argc, char **argv, char **main_class) * this data around. */ if (jarflag && operand) { - if ((res = parse_manifest(operand, &info)) != 0) { + if ((res = JLI_ParseManifest(operand, &info)) != 0) { if (res == -1) ReportErrorMessage2("Unable to access jarfile %s", operand, JNI_TRUE); @@ -839,6 +1009,17 @@ SelectVersion(int argc, char **argv, char **main_class) operand, JNI_TRUE); exit(1); } + + /* + * Command line splash screen option should have precedence + * over the manifest, so the manifest data is used only if + * splash_file_name has not been initialized above during command + * line parsing + */ + if (!headlessflag && !splash_file_name && info.splashscreen_image_file_name) { + splash_file_name = info.splashscreen_image_file_name; + splash_jar_name = operand; + } } else { info.manifest_version = NULL; info.main_class = NULL; @@ -846,6 +1027,22 @@ SelectVersion(int argc, char **argv, char **main_class) info.jre_restrict_search = 0; } + /* + * Passing on splash screen info in environment variables + */ + if (splash_file_name && !headlessflag) { + char* splash_file_entry = JLI_MemAlloc(strlen(SPLASH_FILE_ENV_ENTRY "=")+strlen(splash_file_name)+1); + strcpy(splash_file_entry, SPLASH_FILE_ENV_ENTRY "="); + strcat(splash_file_entry, splash_file_name); + putenv(splash_file_entry); + } + if (splash_jar_name && !headlessflag) { + char* splash_jar_entry = JLI_MemAlloc(strlen(SPLASH_JAR_ENV_ENTRY "=")+strlen(splash_jar_name)+1); + strcpy(splash_jar_entry, SPLASH_JAR_ENV_ENTRY "="); + strcat(splash_jar_entry, splash_jar_name); + putenv(splash_jar_entry); + } + /* * The JRE-Version and JRE-Restrict-Search values (if any) from the * manifest are overwritten by any specified on the command line. @@ -860,22 +1057,22 @@ SelectVersion(int argc, char **argv, char **main_class) * main_class as a side-effect of this routine. */ if (info.main_class != NULL) - *main_class = strdup(info.main_class); + *main_class = JLI_StringDup(info.main_class); /* * If no version selection information is found either on the command * line or in the manifest, simply return. */ if (info.jre_version == NULL) { - free_manifest(); - free(new_argv); + JLI_FreeManifest(); + JLI_MemFree(new_argv); return; } /* * Check for correct syntax of the version specification (JSR 56). */ - if (!valid_version_string(info.jre_version)) { + if (!JLI_ValidVersionString(info.jre_version)) { ReportErrorMessage2("Syntax error in version specification \"%s\"", info.jre_version, JNI_TRUE); exit(1); @@ -894,9 +1091,9 @@ SelectVersion(int argc, char **argv, char **main_class) (info.jre_version?info.jre_version:"null"), (info.jre_restrict_search?"true":"false"), (jre?jre:"null")); if (jre == NULL) { - if (acceptable_release(FULL_VERSION, info.jre_version)) { - free_manifest(); - free(new_argv); + if (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) { + JLI_FreeManifest(); + JLI_MemFree(new_argv); return; } else { ReportErrorMessage2( @@ -918,12 +1115,18 @@ SelectVersion(int argc, char **argv, char **main_class) * to avoid locating, expanding and parsing the manifest extra * times. */ - if (info.main_class != NULL) - (void)strcat(env_entry, info.main_class); + if (info.main_class != NULL) { + if (strlen(info.main_class) <= MAXNAMELEN) { + (void)strcat(env_entry, info.main_class); + } else { + ReportErrorMessage("Error: main-class: attribute exceeds system limits\n", JNI_TRUE); + exit(1); + } + } (void)putenv(env_entry); ExecJRE(jre, new_argv); - free_manifest(); - free(new_argv); + JLI_FreeManifest(); + JLI_MemFree(new_argv); return; } #endif /* ifndef GAMMA */ @@ -937,7 +1140,7 @@ SelectVersion(int argc, char **argv, char **main_class) */ static jboolean ParseArguments(int *pargc, char ***pargv, char **pjarfile, - char **pclassname, int *pret) + char **pclassname, int *pret, const char *jvmpath) { int argc = *pargc; char **argv = *pargv; @@ -970,7 +1173,7 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, } else if (strcmp(arg, "-showversion") == 0) { showVersion = JNI_TRUE; } else if (strcmp(arg, "-X") == 0) { - *pret = PrintXUsage(); + *pret = PrintXUsage(jvmpath); return JNI_FALSE; /* * The following case provide backward compatibility with old-style @@ -1003,7 +1206,7 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, noExitErrorMessage = 1; } else if (strncmp(arg, "-prof", 5) == 0) { char *p = arg + 5; - char *tmp = MemAlloc(strlen(arg) + 50); + char *tmp = JLI_MemAlloc(strlen(arg) + 50); if (*p) { sprintf(tmp, "-Xrunhprof:cpu=old,file=%s", p + 1); } else { @@ -1014,7 +1217,7 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, strncmp(arg, "-oss", 4) == 0 || strncmp(arg, "-ms", 3) == 0 || strncmp(arg, "-mx", 3) == 0) { - char *tmp = MemAlloc(strlen(arg) + 6); + char *tmp = JLI_MemAlloc(strlen(arg) + 6); sprintf(tmp, "-X%s", arg + 1); /* skip '-' */ AddOption(tmp, NULL); } else if (strcmp(arg, "-checksource") == 0 || @@ -1026,7 +1229,8 @@ ParseArguments(int *pargc, char ***pargv, char **pjarfile, arg); } else if (strncmp(arg, "-version:", 9) == 0 || strcmp(arg, "-no-jre-restrict-search") == 0 || - strcmp(arg, "-jre-restrict-search") == 0) { + strcmp(arg, "-jre-restrict-search") == 0 || + strncmp(arg, "-splash:", 8) == 0) { ; /* Ignore machine independent options already handled */ } else if (RemovableMachineDependentOption(arg) ) { ; /* Do not pass option to vm. */ @@ -1080,7 +1284,7 @@ InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) } r = ifn->CreateJavaVM(pvm, (void **)penv, &args); - free(options); + JLI_MemFree(options); return r == JNI_OK; } @@ -1088,21 +1292,6 @@ InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) #define NULL_CHECK0(e) if ((e) == 0) return 0 #define NULL_CHECK(e) if ((e) == 0) return -/* - * Returns a pointer to a block of at least 'size' bytes of memory. - * Prints error message and exits if the memory could not be allocated. - */ -void * -MemAlloc(size_t size) -{ - void *p = malloc(size); - if (p == 0) { - perror("malloc"); - exit(1); - } - return p; -} - static jstring platformEncoding = NULL; static jstring getPlatformEncoding(JNIEnv *env) { if (platformEncoding == NULL) { @@ -1110,7 +1299,7 @@ static jstring getPlatformEncoding(JNIEnv *env) { if (propname) { jclass cls; jmethodID mid; - NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System")); + NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System")); NULL_CHECK0 (mid = (*env)->GetStaticMethodID( env, cls, "getProperty", @@ -1125,12 +1314,12 @@ static jstring getPlatformEncoding(JNIEnv *env) { static jboolean isEncodingSupported(JNIEnv *env, jstring enc) { jclass cls; jmethodID mid; - NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset")); + NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset")); NULL_CHECK0 (mid = (*env)->GetStaticMethodID( env, cls, "isSupported", "(Ljava/lang/String;)Z")); - return (*env)->CallStaticBooleanMethod (env, cls, mid, enc); + return (*env)->CallStaticBooleanMethod(env, cls, mid, enc); } /* @@ -1154,14 +1343,8 @@ NewPlatformString(JNIEnv *env, char *s) jstring str = 0; (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); if (!(*env)->ExceptionOccurred(env)) { -#ifdef GAMMA - /* We support running JVM with older JDK, so here we have to deal */ - /* with the case that sun.jnu.encoding is undefined (enc == NULL) */ - if (enc != NULL && isEncodingSupported(env, enc) == JNI_TRUE) { -#else if (isEncodingSupported(env, enc) == JNI_TRUE) { -#endif - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", "([BLjava/lang/String;)V")); str = (*env)->NewObject(env, cls, mid, ary, enc); @@ -1172,7 +1355,7 @@ NewPlatformString(JNIEnv *env, char *s) the encoding name, in which the StringCoding class will pickup the iso-8859-1 as the fallback converter for us. */ - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", "([B)V")); str = (*env)->NewObject(env, cls, mid, ary); @@ -1195,7 +1378,7 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc) jarray ary; int i; - NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String")); + NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); for (i = 0; i < strc; i++) { jstring str = NewPlatformString(env, *strv++); @@ -1212,7 +1395,7 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc) static jclass LoadClass(JNIEnv *env, char *name) { - char *buf = MemAlloc(strlen(name) + 1); + char *buf = JLI_MemAlloc(strlen(name) + 1); char *s = buf, *t = name, c; jclass cls; jlong start, end; @@ -1224,9 +1407,8 @@ LoadClass(JNIEnv *env, char *name) c = *t++; *s++ = (c == '.') ? '/' : c; } while (c != '\0'); - // use the application class loader for main-class cls = (*env)->FindClass(env, buf); - free(buf); + JLI_MemFree(buf); if (_launcher_debug) { end = CounterGet(); @@ -1251,7 +1433,7 @@ GetMainClassName(JNIEnv *env, char *jarname) jobject jar, man, attr; jstring str, result = 0; - NULL_CHECK0(cls = FindBootStrapClass(env, "java/util/jar/JarFile")); + NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "", "(Ljava/lang/String;)V")); NULL_CHECK0(str = NewPlatformString(env, jarname)); @@ -1282,16 +1464,18 @@ static char *java_args[] = JAVA_ARGS; static char *app_classpath[] = APP_CLASSPATH; /* - * For tools convert 'javac -J-ms32m' to 'java -ms32m ...' + * For tools, convert command line args thus: + * javac -cp foo:foo/"*" -J-ms32m ... + * java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ... */ static void -TranslateDashJArgs(int *pargc, char ***pargv) +TranslateApplicationArgs(int *pargc, char ***pargv) { const int NUM_ARGS = (sizeof(java_args) / sizeof(char *)); int argc = *pargc; char **argv = *pargv; int nargc = argc + NUM_ARGS; - char **nargv = MemAlloc((nargc + 1) * sizeof(char *)); + char **nargv = JLI_MemAlloc((nargc + 1) * sizeof(char *)); int i; *pargc = nargc; @@ -1326,9 +1510,22 @@ TranslateDashJArgs(int *pargc, char ***pargv) } for (i = 0; i < argc; i++) { char *arg = argv[i]; - if (arg[0] != '-' || arg[1] != 'J') { - *nargv++ = arg; + if (arg[0] == '-') { + if (arg[1] == 'J') + continue; +#ifdef EXPAND_CLASSPATH_WILDCARDS + if (arg[1] == 'c' + && (strcmp(arg, "-cp") == 0 || + strcmp(arg, "-classpath") == 0) + && i < argc - 1) { + *nargv++ = arg; + *nargv++ = (char *) JLI_WildcardExpandClasspath(argv[i+1]); + i++; + continue; + } +#endif } + *nargv++ = arg; } *nargv = 0; } @@ -1350,18 +1547,21 @@ static jboolean AddApplicationOptions() { const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *)); - char *s, *envcp, *appcp, *apphome; + char *envcp, *appcp, *apphome; char home[MAXPATHLEN]; /* application home */ char separator[] = { PATH_SEPARATOR, '\0' }; int size, i; int strlenHome; - s = getenv("CLASSPATH"); - if (s) { - /* 40 for -Denv.class.path= */ - envcp = (char *)MemAlloc(strlen(s) + 40); - sprintf(envcp, "-Denv.class.path=%s", s); - AddOption(envcp, NULL); + { + const char *s = getenv("CLASSPATH"); + if (s) { + s = (char *) JLI_WildcardExpandClasspath(s); + /* 40 for -Denv.class.path= */ + envcp = (char *)JLI_MemAlloc(strlen(s) + 40); + sprintf(envcp, "-Denv.class.path=%s", s); + AddOption(envcp, NULL); + } } if (!GetApplicationHome(home, sizeof(home))) { @@ -1370,7 +1570,7 @@ AddApplicationOptions() } /* 40 for '-Dapplication.home=' */ - apphome = (char *)MemAlloc(strlen(home) + 40); + apphome = (char *)JLI_MemAlloc(strlen(home) + 40); sprintf(apphome, "-Dapplication.home=%s", home); AddOption(apphome, NULL); @@ -1380,7 +1580,7 @@ AddApplicationOptions() for (i = 0; i < NUM_APP_CLASSPATH; i++) { size += strlenHome + (int)strlen(app_classpath[i]) + 1; /* 1: separator */ } - appcp = (char *)MemAlloc(size + 1); + appcp = (char *)JLI_MemAlloc(size + 1); strcpy(appcp, "-Djava.class.path="); for (i = 0; i < NUM_APP_CLASSPATH; i++) { strcat(appcp, home); /* c:\program files\myapp */ @@ -1391,7 +1591,7 @@ AddApplicationOptions() AddOption(appcp, NULL); return JNI_TRUE; } -#endif +#endif /* JAVA_ARGS */ /* * inject the -Dsun.java.command pseudo property into the args structure @@ -1433,7 +1633,7 @@ SetJavaCommandLineProp(char *classname, char *jarfile, } /* allocate the memory */ - javaCommand = (char*) MemAlloc(len + strlen(dashDstr) + 1); + javaCommand = (char*) JLI_MemAlloc(len + strlen(dashDstr) + 1); /* build the -D string */ *javaCommand = '\0'; @@ -1455,13 +1655,12 @@ SetJavaCommandLineProp(char *classname, char *jarfile, } /* - * JVM wants to know launcher type, so tell it. + * JVM would like to know if it's created by a standard Sun launcher, or by + * user native application, the following property indicates the former. */ -#ifdef GAMMA void SetJavaLauncherProp() { AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL); } -#endif /* * Prints the version information from the java.version and other properties. @@ -1472,7 +1671,7 @@ PrintJavaVersion(JNIEnv *env) jclass ver; jmethodID print; - NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); + NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version")); NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, "print", "()V")); (*env)->CallStaticVoidMethod(env, ver, print); @@ -1484,7 +1683,9 @@ PrintJavaVersion(JNIEnv *env) static void PrintUsage(void) { +#ifndef GAMMA int i; +#endif fprintf(stdout, "Usage: %s [-options] class [args...]\n" @@ -1515,7 +1716,6 @@ PrintUsage(void) "the \"%s\" VM [deprecated]\n", knownVMs[i].name, knownVMs[i].alias+1); } - /* The first known VM is the default */ { const char* defaultVM = knownVMs[0].name+1; @@ -1568,6 +1768,8 @@ PrintUsage(void) " load native agent library by full pathname\n" " -javaagent:[=]\n" " load Java programming language agent, see java.lang.instrument\n" +" -splash:\n" +" show splash screen with specified image\n" ,PATH_SEPARATOR); } @@ -1576,14 +1778,21 @@ PrintUsage(void) * Print usage message for -X options. */ static jint -PrintXUsage(void) +PrintXUsage(const char *jvmpath) { - char path[MAXPATHLEN]; + /* + A 32 bit cushion to prevent buffer overrun, noting that + fopen(3C) may fail if the buffer exceeds MAXPATHLEN. + */ + char path[MAXPATHLEN+32]; char buf[128]; size_t n; FILE *fp; + static const char Xusage_txt[] = "/Xusage.txt"; - GetXUsagePath(path, sizeof(path)); + strcpy(path, jvmpath); + /* Note the FILE_SEPARATOR is platform dependent */ + strcpy(strrchr(path, FILE_SEPARATOR), Xusage_txt); fp = fopen(path, "r"); if (fp == 0) { fprintf(stderr, "Can't open %s\n", path); @@ -1597,7 +1806,6 @@ PrintXUsage(void) } #ifndef GAMMA - /* * Read the jvm.cfg file and fill the knownJVMs[] array. * @@ -1660,8 +1868,8 @@ ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) jlong start, end; int vmType; char *tmpPtr; - char *altVMName; - char *serverClassVMName; + char *altVMName = NULL; + char *serverClassVMName = NULL; static char *whiteSpace = " \t"; if (_launcher_debug) { start = CounterGet(); @@ -1700,7 +1908,7 @@ ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) fprintf(stderr, "Warning: missing VM type on line %d of `%s'\n", lineno, jvmCfgName); } else { - /* Null-terminate this string for strdup below */ + /* Null-terminate this string for JLI_StringDup below */ *tmpPtr++ = 0; tmpPtr += strspn(tmpPtr, whiteSpace); if (*tmpPtr == 0) { @@ -1758,20 +1966,20 @@ ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative) if (_launcher_debug) printf("jvm.cfg[%d] = ->%s<-\n", cnt, line); if (vmType != VM_UNKNOWN) { - knownVMs[cnt].name = strdup(line); + knownVMs[cnt].name = JLI_StringDup(line); knownVMs[cnt].flag = vmType; switch (vmType) { default: break; case VM_ALIASED_TO: - knownVMs[cnt].alias = strdup(altVMName); + knownVMs[cnt].alias = JLI_StringDup(altVMName); if (_launcher_debug) { printf(" name: %s vmType: %s alias: %s\n", knownVMs[cnt].name, "VM_ALIASED_TO", knownVMs[cnt].alias); } break; case VM_IF_SERVER_CLASS: - knownVMs[cnt].server_class = strdup(serverClassVMName); + knownVMs[cnt].server_class = JLI_StringDup(serverClassVMName); if (_launcher_debug) { printf(" name: %s vmType: %s server_class: %s\n", knownVMs[cnt].name, "VM_IF_SERVER_CLASS", knownVMs[cnt].server_class); @@ -1804,11 +2012,11 @@ GrowKnownVMs(int minimum) if (newMax <= minimum) { newMax = minimum; } - newKnownVMs = (struct vmdesc*) MemAlloc(newMax * sizeof(struct vmdesc)); + newKnownVMs = (struct vmdesc*) JLI_MemAlloc(newMax * sizeof(struct vmdesc)); if (knownVMs != NULL) { memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc)); } - free(knownVMs); + JLI_MemFree(knownVMs); knownVMs = newKnownVMs; knownVMsLimit = newMax; } @@ -1833,10 +2041,38 @@ FreeKnownVMs() { int i; for (i = 0; i < knownVMsCount; i++) { - free(knownVMs[i].name); + JLI_MemFree(knownVMs[i].name); knownVMs[i].name = NULL; } - free(knownVMs); + JLI_MemFree(knownVMs); +} + + +/* + * Displays the splash screen according to the jar file name + * and image file names stored in environment variables + */ +static void +ShowSplashScreen() +{ + const char *jar_name = getenv(SPLASH_JAR_ENV_ENTRY); + const char *file_name = getenv(SPLASH_FILE_ENV_ENTRY); + int data_size; + void *image_data; + if (jar_name) { + image_data = JLI_JarUnpackFile(jar_name, file_name, &data_size); + if (image_data) { + DoSplashInit(); + DoSplashLoadMemory(image_data, data_size); + JLI_MemFree(image_data); + } + } else if (file_name) { + DoSplashInit(); + DoSplashLoadFile(file_name); + } else { + return; + } + DoSplashSetFileJarName(file_name, jar_name); } #endif /* ifndef GAMMA */ diff --git a/src/os/linux/launcher/java.h b/src/share/tools/launcher/java.h similarity index 82% rename from src/os/linux/launcher/java.h rename to src/share/tools/launcher/java.h index b77855efee924ad2f56ad626c19b41a328ff3c1e..97fba2184f7499f0c8b95dce31f8c9ec1050427b 100644 --- a/src/os/linux/launcher/java.h +++ b/src/share/tools/launcher/java.h @@ -22,10 +22,6 @@ * */ -/* - * Gamma (Hotspot internal engineering test) launcher based on 1.6.0-b28 JDK, - * search "GAMMA" for gamma specific changes. - */ #ifndef _JAVA_H_ #define _JAVA_H_ @@ -35,6 +31,7 @@ */ #include "jni.h" #include "java_md.h" +#include "jli_util.h" /* * Pointers to the needed JNI invocation API, initialized by LoadJavaVM. @@ -89,26 +86,26 @@ void ReportExceptionDescription(JNIEnv * env); jboolean RemovableMachineDependentOption(char * option); void PrintMachineDependentOptions(); +const char *jlong_format_specifier(); +/* + * Block current thread and continue execution in new thread + */ +int ContinueInNewThread(int (JNICALL *continuation)(void *), + jlong stack_size, void * args); + +/* sun.java.launcher.* platform properties. */ +void SetJavaLauncherPlatformProps(void); + /* * Functions defined in java.c and used in java_md.c. */ jint ReadKnownVMs(const char *jrepath, char * arch, jboolean speculative); char *CheckJvmType(int *argc, char ***argv, jboolean speculative); -void* MemAlloc(size_t size); +void AddOption(char *str, void *info); /* * Make launcher spit debug output. */ extern jboolean _launcher_debug; -/* - * This allows for finding classes from the VM's bootstrap class loader - * directly, FindClass uses the application class loader internally, this will - * cause unnecessary searching of the classpath for the required classes. - */ -typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env, - const char *name, - jboolean throwError)); - -jclass FindBootStrapClass(JNIEnv *env, const char *classname); #endif /* _JAVA_H_ */ diff --git a/src/share/tools/launcher/jli_util.c b/src/share/tools/launcher/jli_util.c new file mode 100644 index 0000000000000000000000000000000000000000..86987be5503b4b96ed973a7af10a8b222e17d63b --- /dev/null +++ b/src/share/tools/launcher/jli_util.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include +#include +#include "jli_util.h" + +#ifdef GAMMA +#ifdef _WINDOWS +#define strdup _strdup +#endif +#endif + +/* + * Returns a pointer to a block of at least 'size' bytes of memory. + * Prints error message and exits if the memory could not be allocated. + */ +void * +JLI_MemAlloc(size_t size) +{ + void *p = malloc(size); + if (p == 0) { + perror("malloc"); + exit(1); + } + return p; +} + +/* + * Equivalent to realloc(size). + * Prints error message and exits if the memory could not be reallocated. + */ +void * +JLI_MemRealloc(void *ptr, size_t size) +{ + void *p = realloc(ptr, size); + if (p == 0) { + perror("realloc"); + exit(1); + } + return p; +} + +/* + * Wrapper over strdup(3C) which prints an error message and exits if memory + * could not be allocated. + */ +char * +JLI_StringDup(const char *s1) +{ + char *s = strdup(s1); + if (s == NULL) { + perror("strdup"); + exit(1); + } + return s; +} + +/* + * Very equivalent to free(ptr). + * Here to maintain pairing with the above routines. + */ +void +JLI_MemFree(void *ptr) +{ + free(ptr); +} diff --git a/src/share/tools/launcher/jli_util.h b/src/share/tools/launcher/jli_util.h new file mode 100644 index 0000000000000000000000000000000000000000..535f7c482c1b0311a3d33e07feb17db39328f0c1 --- /dev/null +++ b/src/share/tools/launcher/jli_util.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 _JLI_UTIL_H +#define _JLI_UTIL_H + +#include + +void *JLI_MemAlloc(size_t size); +void *JLI_MemRealloc(void *ptr, size_t size); +char *JLI_StringDup(const char *s1); +void JLI_MemFree(void *ptr); + +#endif /* _JLI_UTIL_H */ diff --git a/src/share/tools/launcher/wildcard.c b/src/share/tools/launcher/wildcard.c new file mode 100644 index 0000000000000000000000000000000000000000..26a66566cdb06301d43cacb89f5b9b10351350cf --- /dev/null +++ b/src/share/tools/launcher/wildcard.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * Class-Path Wildcards + * + * The syntax for wildcards is a single asterisk. The class path + * foo/"*", e.g., loads all jar files in the directory named foo. + * (This requires careful quotation when used in shell scripts.) + * + * Only files whose names end in .jar or .JAR are matched. + * Files whose names end in .zip, or which have a particular + * magic number, regardless of filename extension, are not + * matched. + * + * Files are considered regardless of whether or not they are + * "hidden" in the UNIX sense, i.e., have names beginning with '.'. + * + * A wildcard only matches jar files, not class files in the same + * directory. If you want to load both class files and jar files from + * a single directory foo then you can say foo:foo/"*", or foo/"*":foo + * if you want the jar files to take precedence. + * + * Subdirectories are not searched recursively, i.e., foo/"*" only + * looks for jar files in foo, not in foo/bar, foo/baz, etc. + * + * Expansion of wildcards is done early, prior to the invocation of a + * program's main method, rather than late, during the class-loading + * process itself. Each element of the input class path containing a + * wildcard is replaced by the (possibly empty) sequence of elements + * generated by enumerating the jar files in the named directory. If + * the directory foo contains a.jar, b.jar, and c.jar, + * e.g., then the class path foo/"*" is expanded into + * foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value + * of the system property java.class.path. + * + * The order in which the jar files in a directory are enumerated in + * the expanded class path is not specified and may vary from platform + * to platform and even from moment to moment on the same machine. A + * well-constructed application should not depend upon any particular + * order. If a specific order is required then the jar files can be + * enumerated explicitly in the class path. + * + * The CLASSPATH environment variable is not treated any differently + * from the -classpath (equiv. -cp) command-line option, + * i.e. wildcards are honored in all these cases. + * + * Class-path wildcards are not honored in the Class-Path jar-manifest + * header. + * + * Class-path wildcards are honored not only by the Java launcher but + * also by most other command-line tools that accept class paths, and + * in particular by javac and javadoc. + * + * Class-path wildcards are not honored in any other kind of path, and + * especially not in the bootstrap class path, which is a mere + * artifact of our implementation and not something that developers + * should use. + * + * Classpath wildcards are only expanded in the Java launcher code, + * supporting the use of wildcards on the command line and in the + * CLASSPATH environment variable. We do not support the use of + * wildcards by applications that embed the JVM. + */ + +#include +#include +#include +#include +#include +#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */ +#include "jli_util.h" + +#ifdef _WIN32 +#include +#else /* Unix */ +#include +#include +#endif /* Unix */ + +static int +exists(const char* filename) +{ +#ifdef _WIN32 + return _access(filename, 0) == 0; +#else + return access(filename, F_OK) == 0; +#endif +} + +#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_))) + +/* + * Wildcard directory iteration. + * WildcardIterator_for(wildcard) returns an iterator. + * Each call to that iterator's next() method returns the basename + * of an entry in the wildcard's directory. The basename's memory + * belongs to the iterator. The caller is responsible for prepending + * the directory name and file separator, if necessary. + * When done with the iterator, call the close method to clean up. + */ +typedef struct WildcardIterator_* WildcardIterator; + +#ifdef _WIN32 +struct WildcardIterator_ +{ + HANDLE handle; + char *firstFile; /* Stupid FindFirstFile...FindNextFile */ +}; + +static WildcardIterator +WildcardIterator_for(const char *wildcard) +{ + WIN32_FIND_DATA find_data; + WildcardIterator it = NEW_(WildcardIterator); + HANDLE handle = FindFirstFile(wildcard, &find_data); + if (handle == INVALID_HANDLE_VALUE) + return NULL; + it->handle = handle; + it->firstFile = find_data.cFileName; + return it; +} + +static char * +WildcardIterator_next(WildcardIterator it) +{ + WIN32_FIND_DATA find_data; + if (it->firstFile != NULL) { + char *firstFile = it->firstFile; + it->firstFile = NULL; + return firstFile; + } + return FindNextFile(it->handle, &find_data) + ? find_data.cFileName : NULL; +} + +static void +WildcardIterator_close(WildcardIterator it) +{ + if (it) { + FindClose(it->handle); + JLI_MemFree(it->firstFile); + JLI_MemFree(it); + } +} + +#else /* Unix */ +struct WildcardIterator_ +{ + DIR *dir; +}; + +static WildcardIterator +WildcardIterator_for(const char *wildcard) +{ + DIR *dir; + int wildlen = strlen(wildcard); + if (wildlen < 2) { + dir = opendir("."); + } else { + char *dirname = JLI_StringDup(wildcard); + dirname[wildlen - 1] = '\0'; + dir = opendir(dirname); + JLI_MemFree(dirname); + } + if (dir == NULL) + return NULL; + else { + WildcardIterator it = NEW_(WildcardIterator); + it->dir = dir; + return it; + } +} + +static char * +WildcardIterator_next(WildcardIterator it) +{ + struct dirent* dirp = readdir(it->dir); + return dirp ? dirp->d_name : NULL; +} + +static void +WildcardIterator_close(WildcardIterator it) +{ + if (it) { + closedir(it->dir); + JLI_MemFree(it); + } +} +#endif /* Unix */ + +static int +equal(const char *s1, const char *s2) +{ + return strcmp(s1, s2) == 0; +} + +/* + * FileList ADT - a dynamic list of C filenames + */ +struct FileList_ +{ + char **files; + int size; + int capacity; +}; +typedef struct FileList_ *FileList; + +static FileList +FileList_new(int capacity) +{ + FileList fl = NEW_(FileList); + fl->capacity = capacity; + fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0])); + fl->size = 0; + return fl; +} + +#ifdef DEBUG_WILDCARD +static void +FileList_print(FileList fl) +{ + int i; + putchar('['); + for (i = 0; i < fl->size; i++) { + if (i > 0) printf(", "); + printf("\"%s\"",fl->files[i]); + } + putchar(']'); +} +#endif + +static void +FileList_free(FileList fl) +{ + if (fl) { + if (fl->files) { + int i; + for (i = 0; i < fl->size; i++) + JLI_MemFree(fl->files[i]); + JLI_MemFree(fl->files); + } + JLI_MemFree(fl); + } +} + +static void +FileList_ensureCapacity(FileList fl, int capacity) +{ + if (fl->capacity < capacity) { + while (fl->capacity < capacity) + fl->capacity *= 2; + fl->files = JLI_MemRealloc(fl->files, + fl->capacity * sizeof(fl->files[0])); + } +} + +static void +FileList_add(FileList fl, char *file) +{ + FileList_ensureCapacity(fl, fl->size+1); + fl->files[fl->size++] = file; +} + +static void +FileList_addSubstring(FileList fl, const char *beg, int len) +{ + char *filename = (char *) JLI_MemAlloc(len+1); + memcpy(filename, beg, len); + filename[len] = '\0'; + FileList_ensureCapacity(fl, fl->size+1); + fl->files[fl->size++] = filename; +} + +static char * +FileList_join(FileList fl, char sep) +{ + int i; + int size; + char *path; + char *p; + for (i = 0, size = 1; i < fl->size; i++) + size += strlen(fl->files[i]) + 1; + + path = JLI_MemAlloc(size); + + for (i = 0, p = path; i < fl->size; i++) { + int len = strlen(fl->files[i]); + if (i > 0) *p++ = sep; + memcpy(p, fl->files[i], len); + p += len; + } + *p = '\0'; + + return path; +} + +static FileList +FileList_split(const char *path, char sep) +{ + const char *p, *q; + int len = strlen(path); + int count; + FileList fl; + for (count = 1, p = path; p < path + len; p++) + count += (*p == sep); + fl = FileList_new(count); + for (p = path;;) { + for (q = p; q <= path + len; q++) { + if (*q == sep || *q == '\0') { + FileList_addSubstring(fl, p, q - p); + if (*q == '\0') + return fl; + p = q + 1; + } + } + } +} + +static int +isJarFileName(const char *filename) +{ + int len = strlen(filename); + return (len >= 4) && + (filename[len - 4] == '.') && + (equal(filename + len - 3, "jar") || + equal(filename + len - 3, "JAR")) && + /* Paranoia: Maybe filename is "DIR:foo.jar" */ + (strchr(filename, PATH_SEPARATOR) == NULL); +} + +static char * +wildcardConcat(const char *wildcard, const char *basename) +{ + int wildlen = strlen(wildcard); + int baselen = strlen(basename); + char *filename = (char *) JLI_MemAlloc(wildlen + baselen); + /* Replace the trailing '*' with basename */ + memcpy(filename, wildcard, wildlen-1); + memcpy(filename+wildlen-1, basename, baselen+1); + return filename; +} + +static FileList +wildcardFileList(const char *wildcard) +{ + const char *basename; + FileList fl = FileList_new(16); + WildcardIterator it = WildcardIterator_for(wildcard); + if (it == NULL) + return NULL; + while ((basename = WildcardIterator_next(it)) != NULL) + if (isJarFileName(basename)) + FileList_add(fl, wildcardConcat(wildcard, basename)); + WildcardIterator_close(it); + return fl; +} + +static int +isWildcard(const char *filename) +{ + int len = strlen(filename); + return (len > 0) && + (filename[len - 1] == '*') && + (len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) && + (! exists(filename)); +} + +static void +FileList_expandWildcards(FileList fl) +{ + int i, j; + for (i = 0; i < fl->size; i++) { + if (isWildcard(fl->files[i])) { + FileList expanded = wildcardFileList(fl->files[i]); + if (expanded != NULL && expanded->size > 0) { + JLI_MemFree(fl->files[i]); + FileList_ensureCapacity(fl, fl->size + expanded->size); + for (j = fl->size - 1; j >= i+1; j--) + fl->files[j+expanded->size-1] = fl->files[j]; + for (j = 0; j < expanded->size; j++) + fl->files[i+j] = expanded->files[j]; + i += expanded->size - 1; + fl->size += expanded->size - 1; + /* fl expropriates expanded's elements. */ + expanded->size = 0; + } + FileList_free(expanded); + } + } +} + +const char * +JLI_WildcardExpandClasspath(const char *classpath) +{ + char *expanded; + FileList fl; + + if (strchr(classpath, '*') == NULL) + return classpath; + fl = FileList_split(classpath, PATH_SEPARATOR); + FileList_expandWildcards(fl); + expanded = FileList_join(fl, PATH_SEPARATOR); + FileList_free(fl); + if (getenv("_JAVA_LAUNCHER_DEBUG") != 0) + printf("Expanded wildcards:\n" + " before: \"%s\"\n" + " after : \"%s\"\n", + classpath, expanded); + return expanded; +} + +#ifdef DEBUG_WILDCARD +static void +wildcardExpandArgv(const char ***argv) +{ + int i; + for (i = 0; (*argv)[i]; i++) { + if (equal((*argv)[i], "-cp") || + equal((*argv)[i], "-classpath")) { + i++; + (*argv)[i] = wildcardExpandClasspath((*argv)[i]); + } + } +} + +static void +debugPrintArgv(char *argv[]) +{ + int i; + putchar('['); + for (i = 0; argv[i]; i++) { + if (i > 0) printf(", "); + printf("\"%s\"", argv[i]); + } + printf("]\n"); +} + +int +main(int argc, char *argv[]) +{ + argv[0] = "java"; + wildcardExpandArgv((const char***)&argv); + debugPrintArgv(argv); + /* execvp("java", argv); */ + return 0; +} +#endif /* DEBUG_WILDCARD */ + +/* Cute little perl prototype implementation.... + +my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":"; + +sub expand($) { + opendir DIR, $_[0] or return $_[0]; + join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR; +} + +sub munge($) { + join $sep, + map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0]; +} + +for (my $i = 0; $i < @ARGV - 1; $i++) { + $ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/; +} + +$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH}; +@ARGV = ("java", @ARGV); +print "@ARGV\n"; +exec @ARGV; + +*/ diff --git a/src/share/tools/launcher/wildcard.h b/src/share/tools/launcher/wildcard.h new file mode 100644 index 0000000000000000000000000000000000000000..5cdd9312cd44d7942d11a76e9bd923cb4a60d834 --- /dev/null +++ b/src/share/tools/launcher/wildcard.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 WILDCARD_H_ +#define WILDCARD_H_ + +#ifdef EXPAND_CLASSPATH_WILDCARDS +const char *JLI_WildcardExpandClasspath(const char *classpath); +#else +#define JLI_WildcardExpandClasspath(s) (s) +#endif + +#endif /* include guard */ diff --git a/src/share/vm/ci/ciCallProfile.hpp b/src/share/vm/ci/ciCallProfile.hpp index 24062d2b5846216871306f2ee3d855d10121d326..f9d10ed16b501888ebfe474cc140715d457490c5 100644 --- a/src/share/vm/ci/ciCallProfile.hpp +++ b/src/share/vm/ci/ciCallProfile.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_CI_CICALLPROFILE_HPP #include "ci/ciClassList.hpp" +#include "memory/allocation.hpp" // ciCallProfile // diff --git a/src/share/vm/ci/ciMethodHandle.hpp b/src/share/vm/ci/ciMethodHandle.hpp index 3b9ea68337dd8ae6156d3232f11f84d0566a3510..7573bffb9a5620be4e9098599d3d8894dd52b5e8 100644 --- a/src/share/vm/ci/ciMethodHandle.hpp +++ b/src/share/vm/ci/ciMethodHandle.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_CI_CIMETHODHANDLE_HPP #define SHARE_VM_CI_CIMETHODHANDLE_HPP +#include "ci/ciInstance.hpp" #include "prims/methodHandles.hpp" // ciMethodHandle diff --git a/src/share/vm/classfile/classLoader.cpp b/src/share/vm/classfile/classLoader.cpp index 1d646ef656b6f2e6788dcdc29542e0094f661fde..00231243233d843244bced3f03f2cb08b39f6c76 100644 --- a/src/share/vm/classfile/classLoader.cpp +++ b/src/share/vm/classfile/classLoader.cpp @@ -48,7 +48,6 @@ #include "runtime/fprofiler.hpp" #include "runtime/handles.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" @@ -61,15 +60,12 @@ #include "utilities/hashtable.hpp" #include "utilities/hashtable.inline.hpp" #ifdef TARGET_OS_FAMILY_linux -# include "hpi_linux.hpp" # include "os_linux.inline.hpp" #endif #ifdef TARGET_OS_FAMILY_solaris -# include "hpi_solaris.hpp" # include "os_solaris.inline.hpp" #endif #ifdef TARGET_OS_FAMILY_windows -# include "hpi_windows.hpp" # include "os_windows.inline.hpp" #endif @@ -208,13 +204,13 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name) { struct stat st; if (os::stat(path, &st) == 0) { // found file, open it - int file_handle = hpi::open(path, 0, 0); + int file_handle = os::open(path, 0, 0); if (file_handle != -1) { // read contents into resource array u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size); size_t num_read = os::read(file_handle, (char*) buffer, st.st_size); // close file - hpi::close(file_handle); + os::close(file_handle); // construct ClassFileStream if (num_read == (size_t)st.st_size) { if (UsePerfData) { @@ -607,18 +603,18 @@ void ClassLoader::load_zip_library() { // Load zip library char path[JVM_MAXPATHLEN]; char ebuf[1024]; - hpi::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip"); - void* handle = hpi::dll_load(path, ebuf, sizeof ebuf); + os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip"); + void* handle = os::dll_load(path, ebuf, sizeof ebuf); if (handle == NULL) { vm_exit_during_initialization("Unable to load ZIP library", path); } // Lookup zip entry points - ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, hpi::dll_lookup(handle, "ZIP_Open")); - ZipClose = CAST_TO_FN_PTR(ZipClose_t, hpi::dll_lookup(handle, "ZIP_Close")); - FindEntry = CAST_TO_FN_PTR(FindEntry_t, hpi::dll_lookup(handle, "ZIP_FindEntry")); - ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, hpi::dll_lookup(handle, "ZIP_ReadEntry")); - ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, hpi::dll_lookup(handle, "ZIP_ReadMappedEntry")); - GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, hpi::dll_lookup(handle, "ZIP_GetNextEntry")); + ZipOpen = CAST_TO_FN_PTR(ZipOpen_t, os::dll_lookup(handle, "ZIP_Open")); + ZipClose = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close")); + FindEntry = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry")); + ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); + ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); + GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) { @@ -627,7 +623,7 @@ void ClassLoader::load_zip_library() { // Lookup canonicalize entry in libjava.dll void *javalib_handle = os::native_java_library(); - CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, hpi::dll_lookup(javalib_handle, "Canonicalize")); + CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize")); // This lookup only works on 1.3. Do not check for non-null here } @@ -1076,7 +1072,7 @@ bool ClassLoader::get_canonical_path(char* orig, char* out, int len) { assert(orig != NULL && out != NULL && len > 0, "bad arguments"); if (CanonicalizeEntry != NULL) { JNIEnv* env = JavaThread::current()->jni_environment(); - if ((CanonicalizeEntry)(env, hpi::native_path(orig), out, len) < 0) { + if ((CanonicalizeEntry)(env, os::native_path(orig), out, len) < 0) { return false; } } else { diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp index 72c848db76772b0814cf2db271aec04031a8291d..8eee5de5448abafccb1aa5e9db4698108cff9bb2 100644 --- a/src/share/vm/classfile/javaClasses.cpp +++ b/src/share/vm/classfile/javaClasses.cpp @@ -182,7 +182,7 @@ Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRA if (_to_java_string_fn == NULL) { void *lib_handle = os::native_java_library(); - _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, hpi::dll_lookup(lib_handle, "NewStringPlatform")); + _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "NewStringPlatform")); if (_to_java_string_fn == NULL) { fatal("NewStringPlatform missing"); } @@ -207,7 +207,7 @@ char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) { if (_to_platform_string_fn == NULL) { void *lib_handle = os::native_java_library(); - _to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, hpi::dll_lookup(lib_handle, "GetStringPlatformChars")); + _to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, os::dll_lookup(lib_handle, "GetStringPlatformChars")); if (_to_platform_string_fn == NULL) { fatal("GetStringPlatformChars missing"); } @@ -313,6 +313,14 @@ char* java_lang_String::as_utf8_string(oop java_string) { return UNICODE::as_utf8(position, length); } +char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) { + typeArrayOop value = java_lang_String::value(java_string); + int offset = java_lang_String::offset(java_string); + int length = java_lang_String::length(java_string); + jchar* position = (length == 0) ? NULL : value->char_at_addr(offset); + return UNICODE::as_utf8(position, length, buf, buflen); +} + char* java_lang_String::as_utf8_string(oop java_string, int start, int len) { typeArrayOop value = java_lang_String::value(java_string); int offset = java_lang_String::offset(java_string); diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp index 9051390cd6c4503175a3c7fafc79edec25e352b9..bb65db96158a3e07619aa0b5ecff48d46cd4071c 100644 --- a/src/share/vm/classfile/javaClasses.hpp +++ b/src/share/vm/classfile/javaClasses.hpp @@ -104,6 +104,7 @@ class java_lang_String : AllStatic { // String converters static char* as_utf8_string(oop java_string); + static char* as_utf8_string(oop java_string, char* buf, int buflen); static char* as_utf8_string(oop java_string, int start, int len); static char* as_platform_dependent_str(Handle java_string, TRAPS); static jchar* as_unicode_string(oop java_string, int& length); diff --git a/src/share/vm/classfile/placeholders.hpp b/src/share/vm/classfile/placeholders.hpp index 4c77fefff74ea4750d73d3015fe254a6b302b0e0..82c7aaffff87d55df273dbbf19fe8dcedfe7c23c 100644 --- a/src/share/vm/classfile/placeholders.hpp +++ b/src/share/vm/classfile/placeholders.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP #define SHARE_VM_CLASSFILE_PLACEHOLDERS_HPP +#include "runtime/thread.hpp" #include "utilities/hashtable.hpp" class PlaceholderEntry; diff --git a/src/share/vm/classfile/verifier.cpp b/src/share/vm/classfile/verifier.cpp index 5e7f576691eecc492244023257f272cb200e97c3..2690ac3f7bfc5dbb6648bf6cb63bd6d2db25a554 100644 --- a/src/share/vm/classfile/verifier.cpp +++ b/src/share/vm/classfile/verifier.cpp @@ -38,7 +38,6 @@ #include "prims/jvm.h" #include "runtime/fieldDescriptor.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/javaCalls.hpp" #include "runtime/orderAccess.hpp" @@ -69,11 +68,11 @@ static volatile jint _is_new_verify_byte_codes_fn = (jint) true; static void* verify_byte_codes_fn() { if (_verify_byte_codes_fn == NULL) { void *lib_handle = os::native_java_library(); - void *func = hpi::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion"); + void *func = os::dll_lookup(lib_handle, "VerifyClassCodesForMajorVersion"); OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func); if (func == NULL) { OrderAccess::release_store(&_is_new_verify_byte_codes_fn, false); - func = hpi::dll_lookup(lib_handle, "VerifyClassCodes"); + func = os::dll_lookup(lib_handle, "VerifyClassCodes"); OrderAccess::release_store_ptr(&_verify_byte_codes_fn, func); } } diff --git a/src/share/vm/code/vtableStubs.hpp b/src/share/vm/code/vtableStubs.hpp index 6b2b79596e2671cfc5afdfca0817286a4bed8c46..82caf1193fe809e01398f96e7a53d564e19a75fd 100644 --- a/src/share/vm/code/vtableStubs.hpp +++ b/src/share/vm/code/vtableStubs.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_CODE_VTABLESTUBS_HPP #define SHARE_VM_CODE_VTABLESTUBS_HPP +#include "code/vmreg.hpp" #include "memory/allocation.hpp" // A VtableStub holds an individual code stub for a pair (vtable index, #args) for either itables or vtables diff --git a/src/share/vm/compiler/disassembler.cpp b/src/share/vm/compiler/disassembler.cpp index b63b5564908699c8b33cbf5374020f9aaf1581c1..0dff444a4b4d380d485717dd8016927ce118f685 100644 --- a/src/share/vm/compiler/disassembler.cpp +++ b/src/share/vm/compiler/disassembler.cpp @@ -30,7 +30,6 @@ #include "memory/cardTableModRefBS.hpp" #include "runtime/fprofiler.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #ifdef TARGET_ARCH_x86 @@ -84,17 +83,17 @@ bool Disassembler::load_library() { // Find the disassembler next to libjvm.so. strcpy(&buf[jvm_offset], hsdis_library_name); strcat(&buf[jvm_offset], os::dll_file_extension()); - _library = hpi::dll_load(buf, ebuf, sizeof ebuf); + _library = os::dll_load(buf, ebuf, sizeof ebuf); } if (_library == NULL) { // Try a free-floating lookup. strcpy(&buf[0], hsdis_library_name); strcat(&buf[0], os::dll_file_extension()); - _library = hpi::dll_load(buf, ebuf, sizeof ebuf); + _library = os::dll_load(buf, ebuf, sizeof ebuf); } if (_library != NULL) { _decode_instructions = CAST_TO_FN_PTR(Disassembler::decode_func, - hpi::dll_lookup(_library, decode_instructions_name)); + os::dll_lookup(_library, decode_instructions_name)); } _tried_to_load_library = true; if (_decode_instructions == NULL) { diff --git a/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp b/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp index be7abd60655ff11595765e067b822a4c8e6f4ef0..6d1504a8653e8169b7dd9b596021185efaf0a47f 100644 --- a/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp +++ b/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP #include "memory/allocation.hpp" +#include "memory/blockOffsetTable.hpp" #include "memory/threadLocalAllocBuffer.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp index 9f8c2042bd603180392691871f502a9203d44951..e6a07310dbf99ec9bd45b99aca75faee374be93c 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_HPP +#include "memory/memRegion.hpp" #include "gc_implementation/parallelScavenge/psVirtualspace.hpp" #include "utilities/bitMap.inline.hpp" diff --git a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp index e94f75c6e2707ad8885bc788f9fb8ed9ea67c521..e7f1dfa5470568bcb085f35f052c58eeece46d90 100644 --- a/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp +++ b/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.inline.hpp @@ -25,6 +25,8 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PARMARKBITMAP_INLINE_HPP +#include "oops/oop.hpp" + inline bool ParMarkBitMap::mark_obj(oop obj) { diff --git a/src/share/vm/interpreter/bytecodeInterpreter.cpp b/src/share/vm/interpreter/bytecodeInterpreter.cpp index 686d1469abb76b672c189cc8de78ed62e7d14424..16ec3ff6081811a862a06fa269c6883b8e9cb313 100644 --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp @@ -1323,12 +1323,7 @@ run: jfloat f; jdouble r; f = STACK_FLOAT(-1); -#ifdef IA64 - // IA64 gcc bug - r = ( f == 0.0f ) ? (jdouble) f : (jdouble) f + ia64_double_zero; -#else r = (jdouble) f; -#endif MORE_STACK(-1); // POP SET_STACK_DOUBLE(r, 1); UPDATE_PC_AND_TOS_AND_CONTINUE(1, 2); diff --git a/src/share/vm/interpreter/interpreterRuntime.cpp b/src/share/vm/interpreter/interpreterRuntime.cpp index 2aa0c96dc3275865d3be8d04d85bca671122cbc7..494ba1fccbf6b98253335eb3f0644e6a90d2e37a 100644 --- a/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/src/share/vm/interpreter/interpreterRuntime.cpp @@ -1193,9 +1193,20 @@ void SignatureHandlerLibrary::add(methodHandle method) { method->set_signature_handler(_handlers->at(handler_index)); } } +#ifdef ASSERT + int handler_index, fingerprint_index; + { + // '_handlers' and '_fingerprints' are 'GrowableArray's and are NOT synchronized + // in any way if accessed from multiple threads. To avoid races with another + // thread which may change the arrays in the above, mutex protected block, we + // have to protect this read access here with the same mutex as well! + MutexLocker mu(SignatureHandlerLibrary_lock); + handler_index = _handlers->find(method->signature_handler()); + fingerprint_index = _fingerprints->find(Fingerprinter(method).fingerprint()); + } assert(method->signature_handler() == Interpreter::slow_signature_handler() || - _handlers->find(method->signature_handler()) == _fingerprints->find(Fingerprinter(method).fingerprint()), - "sanity check"); + handler_index == fingerprint_index, "sanity check"); +#endif } diff --git a/src/share/vm/interpreter/oopMapCache.hpp b/src/share/vm/interpreter/oopMapCache.hpp index 4c1f0147f9369e95aaa4dc307294da19b5809d5b..068e4d3b9825f05ba68497c8b14be685c885436d 100644 --- a/src/share/vm/interpreter/oopMapCache.hpp +++ b/src/share/vm/interpreter/oopMapCache.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP #include "oops/generateOopMap.hpp" +#include "runtime/mutex.hpp" // A Cache for storing (method, bci) -> oopMap. // The memory management system uses the cache when locating object diff --git a/src/share/vm/libadt/vectset.cpp b/src/share/vm/libadt/vectset.cpp index efb1d6638dc1589a63482865abd21570eeb23c57..1dd9f4e26e3ac02588526c4dc681364971d3d0d1 100644 --- a/src/share/vm/libadt/vectset.cpp +++ b/src/share/vm/libadt/vectset.cpp @@ -249,13 +249,13 @@ int VectorSet::disjoint(const Set &set) const const VectorSet &s = *(set.asVectorSet()); // NOTE: The intersection is never any larger than the smallest set. - register uint small = ((sizeprint_cr("Loading classlist failed: %s", errmsg); exit(1); } diff --git a/src/share/vm/memory/filemap.cpp b/src/share/vm/memory/filemap.cpp index 0269a5e5aa3fa800abc62179cf65ed353affa82c..aa9fadc3242bf0bcb8b5eabefecda57996b5654a 100644 --- a/src/share/vm/memory/filemap.cpp +++ b/src/share/vm/memory/filemap.cpp @@ -30,15 +30,6 @@ #include "runtime/java.hpp" #include "runtime/os.hpp" #include "utilities/defaultStream.hpp" -#ifdef TARGET_OS_FAMILY_linux -# include "hpi_linux.hpp" -#endif -#ifdef TARGET_OS_FAMILY_solaris -# include "hpi_solaris.hpp" -#endif -#ifdef TARGET_OS_FAMILY_windows -# include "hpi_windows.hpp" -#endif # include # include diff --git a/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp b/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp index cd8e7a8271308edaebf552c3b93bc7c195810685..ea803157300f6a8d0810ae675cb13e9ecf86f2b3 100644 --- a/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp +++ b/src/share/vm/memory/threadLocalAllocBuffer.inline.hpp @@ -28,6 +28,7 @@ #include "gc_interface/collectedHeap.hpp" #include "memory/threadLocalAllocBuffer.hpp" #include "runtime/atomic.hpp" +#include "runtime/thread.hpp" #include "utilities/copy.hpp" inline HeapWord* ThreadLocalAllocBuffer::allocate(size_t size) { diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp index ba48f8f83b93070a0b3204e9007f221d2d212db5..2bd3acd6f150c1785fd1359fd81fef4f1bb24ad4 100644 --- a/src/share/vm/opto/matcher.cpp +++ b/src/share/vm/opto/matcher.cpp @@ -36,7 +36,6 @@ #include "opto/runtime.hpp" #include "opto/type.hpp" #include "runtime/atomic.hpp" -#include "runtime/hpi.hpp" #include "runtime/os.hpp" #ifdef TARGET_ARCH_MODEL_x86_32 # include "adfiles/ad_x86_32.hpp" diff --git a/src/share/vm/precompiled.hpp b/src/share/vm/precompiled.hpp index b8c33a6697e2c78bff3928ee0a7c14979d168b94..602331ea4afbaa2ff9da2b01cd1987b460a8b011 100644 --- a/src/share/vm/precompiled.hpp +++ b/src/share/vm/precompiled.hpp @@ -22,6 +22,10 @@ * */ +// Precompiled headers are turned off for Sun Studion, +// or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles. +#ifndef DONT_USE_PRECOMPILED_HEADER + # include "asm/assembler.hpp" # include "asm/assembler.inline.hpp" # include "asm/codeBuffer.hpp" @@ -168,7 +172,6 @@ # include "oops/symbolOop.hpp" # include "oops/typeArrayKlass.hpp" # include "oops/typeArrayOop.hpp" -# include "prims/hpi_imported.h" # include "prims/jni.h" # include "prims/jvm.h" # include "prims/jvmtiExport.hpp" @@ -185,7 +188,6 @@ # include "runtime/globals_extension.hpp" # include "runtime/handles.hpp" # include "runtime/handles.inline.hpp" -# include "runtime/hpi.hpp" # include "runtime/icache.hpp" # include "runtime/init.hpp" # include "runtime/interfaceSupport.hpp" @@ -325,3 +327,5 @@ # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp" # include "gc_implementation/shared/gcPolicyCounters.hpp" #endif // SERIALGC + +#endif // !DONT_USE_PRECOMPILED_HEADER diff --git a/src/share/vm/prims/hpi_imported.h b/src/share/vm/prims/hpi_imported.h deleted file mode 100644 index d6620985fd9b6f4aed139ba0326668b29784c3a5..0000000000000000000000000000000000000000 --- a/src/share/vm/prims/hpi_imported.h +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* - * HotSpot integration note: - * - * This is a consolidation of these two files: - * src/share/hpi/export/hpi.h 1.15 99/06/18 JDK1.3 beta build I - * src/share/hpi/export/dll.h 1.3 98/09/15 JDK1.3 beta build I - * from the classic VM. - * - * bool_t is a type in the classic VM, and we define it here, - * but in the future this should be a jboolean. - * - * The files are included verbatim expect for local includes removed from hpi.h. - */ - -#ifndef SHARE_VM_PRIMS_HPI_IMPORTED_H -#define SHARE_VM_PRIMS_HPI_IMPORTED_H - -#include "jni.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* A classic VMism that should become a jboolean. Fix in 1.2.1? */ -typedef enum { HPI_FALSE = 0, HPI_TRUE = 1 } bool_t; - -/* - * DLL.H: A common interface for helper DLLs loaded by the VM. - * Each library exports the main entry point "DLL_Initialize". Through - * that function the programmer can obtain a function pointer which has - * type "GetInterfaceFunc." Through the function pointer the programmer - * can obtain other interfaces supported in the DLL. - */ -typedef jint (JNICALL * GetInterfaceFunc) - (void **intfP, const char *name, jint ver); - -jint JNICALL DLL_Initialize(GetInterfaceFunc *, void *args); - - -/* - * Host Porting Interface. This defines the "porting layer" for - * POSIX.1 compliant operating systems. - */ - -/* - * memory allocations - */ -typedef struct { - /* - * Malloc must return a unique pointer if size == 0. - */ - void * (*Malloc)(size_t size); - void * (*Realloc)(void *ptr, size_t new_size); - /* - * Free must allow ptr == NULL to be a no-op. - */ - void (*Free)(void *ptr); - /* - * Calloc must return a unique pointer for if - * n_item == 0 || item_size == 0. - */ - void * (*Calloc)(size_t n_item, size_t item_size); - char * (*Strdup)(const char *str); - - void * (*MapMem)(size_t req_size, size_t *maped_size); - void * (*UnmapMem)(void *req_addr, size_t req_size, size_t *unmap_size); - /* - * CommitMem should round the ptr down to the nearest page and - * round the size up to the nearest page so that the committed - * region is at least as large as the requested region. - */ - void * (*CommitMem)(void *ptr, size_t size, size_t *actual); - /* - * sysDecommitMem should round the ptr up to the nearest page and - * round the size down to the nearest page so that the decommitted - * region is no greater than the requested region. - */ - void * (*DecommitMem)(void *ptr, size_t size, size_t *actual); - -#define HPI_PAGE_ALIGNMENT (64 * 1024) - - void * (*AllocBlock)(size_t size, void **headP); - void (*FreeBlock)(void *head); -} HPI_MemoryInterface; - -/* - * dynamic linking libraries - */ -typedef struct { - void (*BuildLibName)(char *buf, int buf_len, char *path, const char *name); - int (*BuildFunName)(char *name, int name_len, int arg_size, int en_idx); - - void * (*LoadLibrary)(const char *name, char *err_buf, int err_buflen); - void (*UnloadLibrary)(void *lib); - void * (*FindLibraryEntry)(void *lib, const char *name); -} HPI_LibraryInterface; - -typedef void (*signal_handler_t)(int sig, void *siginfo, void *context); - -#define HPI_SIG_DFL (signal_handler_t)0 -#define HPI_SIG_ERR (signal_handler_t)-1 -#define HPI_SIG_IGN (signal_handler_t)1 - -typedef struct { - char *name; /* name such as green/native threads. */ - int isMP; -} HPI_SysInfo; - -typedef struct { - HPI_SysInfo * (*GetSysInfo)(void); - long (*GetMilliTicks)(void); - jlong (*TimeMillis)(void); - - signal_handler_t (*Signal)(int sig, signal_handler_t handler); - void (*Raise)(int sig); - void (*SignalNotify)(int sig); - int (*SignalWait)(void); - - int (*Shutdown)(void); - - int (*SetLoggingLevel)(int level); - bool_t (*SetMonitoringOn)(bool_t on); - int (*GetLastErrorString)(char *buf, int len); -} HPI_SystemInterface; - -/* - * threads and monitors - */ -typedef struct sys_thread sys_thread_t; -typedef struct sys_mon sys_mon_t; - -#define HPI_OK 0 -#define HPI_ERR -1 -#define HPI_INTRPT -2 /* Operation was interrupted */ -#define HPI_TIMEOUT -3 /* A timer ran out */ -#define HPI_NOMEM -5 /* Ran out of memory */ -#define HPI_NORESOURCE -6 /* Ran out of some system resource */ - -/* There are three basic states: RUNNABLE, MONITOR_WAIT, and CONDVAR_WAIT. - * When the thread is suspended in any of these states, the - * HPI_THREAD_SUSPENDED bit will be set - */ -enum { - HPI_THREAD_RUNNABLE = 1, - HPI_THREAD_MONITOR_WAIT, - HPI_THREAD_CONDVAR_WAIT -}; - -#define HPI_MINIMUM_PRIORITY 1 -#define HPI_MAXIMUM_PRIORITY 10 -#define HPI_NORMAL_PRIORITY 5 - -#define HPI_THREAD_SUSPENDED 0x8000 -#define HPI_THREAD_INTERRUPTED 0x4000 - -typedef struct { - sys_thread_t *owner; - int entry_count; - sys_thread_t **monitor_waiters; - sys_thread_t **condvar_waiters; - int sz_monitor_waiters; - int sz_condvar_waiters; - int n_monitor_waiters; - int n_condvar_waiters; -} sys_mon_info; - -typedef struct { - int (*ThreadBootstrap)(sys_thread_t **tidP, - sys_mon_t **qlockP, - int nReservedBytes); - int (*ThreadCreate)(sys_thread_t **tidP, - long stk_size, - void (*func)(void *), - void *arg); - sys_thread_t * (*ThreadSelf)(void); - void (*ThreadYield)(void); - int (*ThreadSuspend)(sys_thread_t *tid); - int (*ThreadResume)(sys_thread_t *tid); - int (*ThreadSetPriority)(sys_thread_t *tid, int prio); - int (*ThreadGetPriority)(sys_thread_t *tid, int *prio); - void * (*ThreadStackPointer)(sys_thread_t *tid); - void * (*ThreadStackTop)(sys_thread_t *tid); - long * (*ThreadRegs)(sys_thread_t *tid, int *regs); - int (*ThreadSingle)(void); - void (*ThreadMulti)(void); - int (*ThreadEnumerateOver)(int (*func)(sys_thread_t *, void *), - void *arg); - int (*ThreadCheckStack)(void); - void (*ThreadPostException)(sys_thread_t *tid, void *arg); - void (*ThreadInterrupt)(sys_thread_t *tid); - int (*ThreadIsInterrupted)(sys_thread_t *tid, int clear); - int (*ThreadAlloc)(sys_thread_t **tidP); - int (*ThreadFree)(void); - jlong (*ThreadCPUTime)(void); - int (*ThreadGetStatus)(sys_thread_t *tid, sys_mon_t **monitor); - void * (*ThreadInterruptEvent)(void); - void * (*ThreadNativeID)(sys_thread_t *tid); - - /* These three functions are used by the CPU time profiler. - * sysThreadIsRunning determines whether the thread is running (not just - * runnable). It is only safe to call this function after calling - * sysThreadProfSuspend. - */ - bool_t (*ThreadIsRunning)(sys_thread_t *tid); - void (*ThreadProfSuspend)(sys_thread_t *tid); - void (*ThreadProfResume)(sys_thread_t *tid); - - int (*AdjustTimeSlice)(int ms); - - size_t (*MonitorSizeof)(void); - int (*MonitorInit)(sys_mon_t *mid); - int (*MonitorDestroy)(sys_mon_t *mid); - int (*MonitorEnter)(sys_thread_t *self, sys_mon_t *mid); - bool_t (*MonitorEntered)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorExit)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotify)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorNotifyAll)(sys_thread_t *self, sys_mon_t *mid); - int (*MonitorWait)(sys_thread_t *self, sys_mon_t *mid, jlong ms); - bool_t (*MonitorInUse)(sys_mon_t *mid); - sys_thread_t * (*MonitorOwner)(sys_mon_t *mid); - int (*MonitorGetInfo)(sys_mon_t *mid, sys_mon_info *info); - -} HPI_ThreadInterface; - -/* - * files - */ - -#define HPI_FILETYPE_REGULAR (0) -#define HPI_FILETYPE_DIRECTORY (1) -#define HPI_FILETYPE_OTHER (2) - -typedef struct { - char * (*NativePath)(char *path); - int (*FileType)(const char *path); - int (*Open)(const char *name, int openMode, int filePerm); - int (*Close)(int fd); - jlong (*Seek)(int fd, jlong offset, int whence); - int (*SetLength)(int fd, jlong length); - int (*Sync)(int fd); - int (*Available)(int fd, jlong *bytes); - size_t (*Read)(int fd, void *buf, unsigned int nBytes); - size_t (*Write)(int fd, const void *buf, unsigned int nBytes); - int (*FileSizeFD)(int fd, jlong *size); -} HPI_FileInterface; - -/* - * sockets - */ -struct sockaddr; -struct hostent; - -typedef struct { - int (*Close)(int fd); - long (*Available)(int fd, jint *pbytes); - int (*Connect)(int fd, struct sockaddr *him, int len); - int (*Accept)(int fd, struct sockaddr *him, int *len); - int (*SendTo)(int fd, char *buf, int len, int flags, - struct sockaddr *to, int tolen); - int (*RecvFrom)(int fd, char *buf, int nbytes, int flags, - struct sockaddr *from, int *fromlen); - int (*Listen)(int fd, long count); - int (*Recv)(int fd, char *buf, int nBytes, int flags); - int (*Send)(int fd, char *buf, int nBytes, int flags); - int (*Timeout)(int fd, long timeout); - struct hostent * (*GetHostByName)(char *hostname); - int (*Socket)(int domain, int type, int protocol); - int (*SocketShutdown)(int fd, int howto); - int (*Bind)(int fd, struct sockaddr *him, int len); - int (*GetSocketName)(int fd, struct sockaddr *him, int *len); - int (*GetHostName)(char *hostname, int namelen); - struct hostent * (*GetHostByAddr)(const char *hostname, int len, int type); - int (*SocketGetOption)(int fd, int level, int optname, char *optval, int *optlen); - int (*SocketSetOption)(int fd, int level, int optname, const char *optval, int optlen); - struct protoent * (*GetProtoByName)(char* name); -} HPI_SocketInterface; - -/* - * callbacks. - */ -typedef struct vm_calls { - int (*jio_fprintf)(FILE *fp, const char *fmt, ...); - void (*panic)(const char *fmt, ...); - void (*monitorRegister)(sys_mon_t *mid, char *info_str); - - void (*monitorContendedEnter)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedEntered)(sys_thread_t *self, sys_mon_t *mid); - void (*monitorContendedExit)(sys_thread_t *self, sys_mon_t *mid); -} vm_calls_t; - -#ifdef __cplusplus -} -#endif - -#endif // SHARE_VM_PRIMS_HPI_IMPORTED_H diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp index e716546d066ae5f3a38cec0900aa5f047888bc43..2638d7dc4e8f0438c588c81dc628fdbf625900f6 100644 --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -2113,11 +2113,10 @@ JNI_END JNI_ENTRY(const char*, jni_GetStringUTFChars(JNIEnv *env, jstring string, jboolean *isCopy)) JNIWrapper("GetStringUTFChars"); DTRACE_PROBE3(hotspot_jni, GetStringUTFChars__entry, env, string, isCopy); - ResourceMark rm; - char* str = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(string)); - int length = (int)strlen(str); - char* result = AllocateHeap(length+1, "GetStringUTFChars"); - strcpy(result, str); + oop java_string = JNIHandles::resolve_non_null(string); + size_t length = java_lang_String::utf8_length(java_string); + char* result = AllocateHeap(length + 1, "GetStringUTFChars"); + java_lang_String::as_utf8_string(java_string, result, (int) length + 1); if (isCopy != NULL) *isCopy = JNI_TRUE; DTRACE_PROBE1(hotspot_jni, GetStringUTFChars__return, result); return result; @@ -3258,7 +3257,6 @@ struct JavaVM_ main_vm = {&jni_InvokeInterface}; #define JAVASTACKSIZE (400 * 1024) /* Default size of a thread java stack */ -#define PROCSTACKSIZE 0 /* 0 means default size in HPI */ enum { VERIFY_NONE, VERIFY_REMOTE, VERIFY_ALL }; HS_DTRACE_PROBE_DECL1(hotspot_jni, GetDefaultJavaVMInitArgs__entry, void*); diff --git a/src/share/vm/prims/jniCheck.cpp b/src/share/vm/prims/jniCheck.cpp index 43a84089ea3480a4ec1e2b57249c49e9419680b3..0b332cd874703c7576f4a9acd5f3782b14f9ce11 100644 --- a/src/share/vm/prims/jniCheck.cpp +++ b/src/share/vm/prims/jniCheck.cpp @@ -1288,6 +1288,9 @@ JNI_ENTRY_CHECKED(jsize, return result; JNI_END +// Arbitrary (but well-known) tag +const jint STRING_TAG = 0x47114711; + JNI_ENTRY_CHECKED(const jchar *, checked_jni_GetStringChars(JNIEnv *env, jstring str, @@ -1297,8 +1300,19 @@ JNI_ENTRY_CHECKED(const jchar *, checkString(thr, str); ) const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy); + assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected"); + + size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination + jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), "checked_jni_GetStringChars"); + *tagLocation = STRING_TAG; + jchar* newResult = (jchar*) (tagLocation + 1); + memcpy(newResult, result, len * sizeof(jchar)); + // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes + // Note that the dtrace arguments for the allocated memory will not match up with this solution. + FreeHeap((char*)result); + functionExit(env); - return result; + return newResult; JNI_END JNI_ENTRY_CHECKED(void, @@ -1309,11 +1323,17 @@ JNI_ENTRY_CHECKED(void, IN_VM( checkString(thr, str); ) - /* cannot check validity of copy, unless every request is logged by - * checking code. Implementation of this check is deferred until a - * subsequent release. - */ - UNCHECKED()->ReleaseStringChars(env,str,chars); + if (chars == NULL) { + // still do the unchecked call to allow dtrace probes + UNCHECKED()->ReleaseStringChars(env,str,chars); + } + else { + jint* tagLocation = ((jint*) chars) - 1; + if (*tagLocation != STRING_TAG) { + NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars"); + } + UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation); + } functionExit(env); JNI_END @@ -1338,6 +1358,9 @@ JNI_ENTRY_CHECKED(jsize, return result; JNI_END +// Arbitrary (but well-known) tag - different than GetStringChars +const jint STRING_UTF_TAG = 0x48124812; + JNI_ENTRY_CHECKED(const char *, checked_jni_GetStringUTFChars(JNIEnv *env, jstring str, @@ -1347,8 +1370,19 @@ JNI_ENTRY_CHECKED(const char *, checkString(thr, str); ) const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy); + assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected"); + + size_t len = strlen(result) + 1; // + 1 for NULL termination + jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), "checked_jni_GetStringUTFChars"); + *tagLocation = STRING_UTF_TAG; + char* newResult = (char*) (tagLocation + 1); + strcpy(newResult, result); + // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes + // Note that the dtrace arguments for the allocated memory will not match up with this solution. + FreeHeap((char*)result); + functionExit(env); - return result; + return newResult; JNI_END JNI_ENTRY_CHECKED(void, @@ -1359,11 +1393,17 @@ JNI_ENTRY_CHECKED(void, IN_VM( checkString(thr, str); ) - /* cannot check validity of copy, unless every request is logged by - * checking code. Implementation of this check is deferred until a - * subsequent release. - */ - UNCHECKED()->ReleaseStringUTFChars(env,str,chars); + if (chars == NULL) { + // still do the unchecked call to allow dtrace probes + UNCHECKED()->ReleaseStringUTFChars(env,str,chars); + } + else { + jint* tagLocation = ((jint*) chars) - 1; + if (*tagLocation != STRING_UTF_TAG) { + NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars"); + } + UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation); + } functionExit(env); JNI_END diff --git a/src/share/vm/prims/jvm.cpp b/src/share/vm/prims/jvm.cpp index 64d1640d6e698fdbb925d26d10c85ee978518a80..76dcd92cd3983e8eafcbddeba5205d2c4fba79fa 100644 --- a/src/share/vm/prims/jvm.cpp +++ b/src/share/vm/prims/jvm.cpp @@ -43,7 +43,6 @@ #include "runtime/arguments.hpp" #include "runtime/dtraceJSDT.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/hpi.hpp" #include "runtime/init.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/java.hpp" @@ -65,15 +64,12 @@ #include "utilities/top.hpp" #include "utilities/utf8.hpp" #ifdef TARGET_OS_FAMILY_linux -# include "hpi_linux.hpp" # include "jvm_linux.h" #endif #ifdef TARGET_OS_FAMILY_solaris -# include "hpi_solaris.hpp" # include "jvm_solaris.h" #endif #ifdef TARGET_OS_FAMILY_windows -# include "hpi_windows.hpp" # include "jvm_windows.h" #endif @@ -653,7 +649,7 @@ JVM_END JVM_LEAF(jint, JVM_GetLastErrorString(char *buf, int len)) JVMWrapper("JVM_GetLastErrorString"); - return hpi::lasterror(buf, len); + return (jint)os::lasterror(buf, len); JVM_END @@ -661,7 +657,7 @@ JVM_END JVM_LEAF(char*, JVM_NativePath(char* path)) JVMWrapper2("JVM_NativePath (%s)", path); - return hpi::native_path(path); + return os::native_path(path); JVM_END @@ -2487,7 +2483,7 @@ JVM_LEAF(jint, JVM_Open(const char *fname, jint flags, jint mode)) JVMWrapper2("JVM_Open (%s)", fname); //%note jvm_r6 - int result = hpi::open(fname, flags, mode); + int result = os::open(fname, flags, mode); if (result >= 0) { return result; } else { @@ -2504,7 +2500,7 @@ JVM_END JVM_LEAF(jint, JVM_Close(jint fd)) JVMWrapper2("JVM_Close (0x%x)", fd); //%note jvm_r6 - return hpi::close(fd); + return os::close(fd); JVM_END @@ -2512,7 +2508,7 @@ JVM_LEAF(jint, JVM_Read(jint fd, char *buf, jint nbytes)) JVMWrapper2("JVM_Read (0x%x)", fd); //%note jvm_r6 - return (jint)hpi::read(fd, buf, nbytes); + return (jint)os::restartable_read(fd, buf, nbytes); JVM_END @@ -2520,34 +2516,34 @@ JVM_LEAF(jint, JVM_Write(jint fd, char *buf, jint nbytes)) JVMWrapper2("JVM_Write (0x%x)", fd); //%note jvm_r6 - return (jint)hpi::write(fd, buf, nbytes); + return (jint)os::write(fd, buf, nbytes); JVM_END JVM_LEAF(jint, JVM_Available(jint fd, jlong *pbytes)) JVMWrapper2("JVM_Available (0x%x)", fd); //%note jvm_r6 - return hpi::available(fd, pbytes); + return os::available(fd, pbytes); JVM_END JVM_LEAF(jlong, JVM_Lseek(jint fd, jlong offset, jint whence)) JVMWrapper4("JVM_Lseek (0x%x, %Ld, %d)", fd, offset, whence); //%note jvm_r6 - return hpi::lseek(fd, offset, whence); + return os::lseek(fd, offset, whence); JVM_END JVM_LEAF(jint, JVM_SetLength(jint fd, jlong length)) JVMWrapper3("JVM_SetLength (0x%x, %Ld)", fd, length); - return hpi::ftruncate(fd, length); + return os::ftruncate(fd, length); JVM_END JVM_LEAF(jint, JVM_Sync(jint fd)) JVMWrapper2("JVM_Sync (0x%x)", fd); //%note jvm_r6 - return hpi::fsync(fd); + return os::fsync(fd); JVM_END @@ -3457,146 +3453,125 @@ JVM_END JVM_LEAF(jint, JVM_InitializeSocketLibrary()) JVMWrapper("JVM_InitializeSocketLibrary"); - return hpi::initialize_socket_library(); + return 0; JVM_END JVM_LEAF(jint, JVM_Socket(jint domain, jint type, jint protocol)) JVMWrapper("JVM_Socket"); - return hpi::socket(domain, type, protocol); + return os::socket(domain, type, protocol); JVM_END JVM_LEAF(jint, JVM_SocketClose(jint fd)) JVMWrapper2("JVM_SocketClose (0x%x)", fd); //%note jvm_r6 - return hpi::socket_close(fd); + return os::socket_close(fd); JVM_END JVM_LEAF(jint, JVM_SocketShutdown(jint fd, jint howto)) JVMWrapper2("JVM_SocketShutdown (0x%x)", fd); //%note jvm_r6 - return hpi::socket_shutdown(fd, howto); + return os::socket_shutdown(fd, howto); JVM_END JVM_LEAF(jint, JVM_Recv(jint fd, char *buf, jint nBytes, jint flags)) JVMWrapper2("JVM_Recv (0x%x)", fd); //%note jvm_r6 - return hpi::recv(fd, buf, nBytes, flags); + return os::recv(fd, buf, nBytes, flags); JVM_END JVM_LEAF(jint, JVM_Send(jint fd, char *buf, jint nBytes, jint flags)) JVMWrapper2("JVM_Send (0x%x)", fd); //%note jvm_r6 - return hpi::send(fd, buf, nBytes, flags); + return os::send(fd, buf, nBytes, flags); JVM_END JVM_LEAF(jint, JVM_Timeout(int fd, long timeout)) JVMWrapper2("JVM_Timeout (0x%x)", fd); //%note jvm_r6 - return hpi::timeout(fd, timeout); + return os::timeout(fd, timeout); JVM_END JVM_LEAF(jint, JVM_Listen(jint fd, jint count)) JVMWrapper2("JVM_Listen (0x%x)", fd); //%note jvm_r6 - return hpi::listen(fd, count); + return os::listen(fd, count); JVM_END JVM_LEAF(jint, JVM_Connect(jint fd, struct sockaddr *him, jint len)) JVMWrapper2("JVM_Connect (0x%x)", fd); //%note jvm_r6 - return hpi::connect(fd, him, len); + return os::connect(fd, him, len); JVM_END JVM_LEAF(jint, JVM_Bind(jint fd, struct sockaddr *him, jint len)) JVMWrapper2("JVM_Bind (0x%x)", fd); //%note jvm_r6 - return hpi::bind(fd, him, len); + return os::bind(fd, him, len); JVM_END JVM_LEAF(jint, JVM_Accept(jint fd, struct sockaddr *him, jint *len)) JVMWrapper2("JVM_Accept (0x%x)", fd); //%note jvm_r6 - return hpi::accept(fd, him, (int *)len); + return os::accept(fd, him, (int *)len); JVM_END JVM_LEAF(jint, JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen)) JVMWrapper2("JVM_RecvFrom (0x%x)", fd); //%note jvm_r6 - return hpi::recvfrom(fd, buf, nBytes, flags, from, fromlen); + return os::recvfrom(fd, buf, nBytes, flags, from, fromlen); JVM_END JVM_LEAF(jint, JVM_GetSockName(jint fd, struct sockaddr *him, int *len)) JVMWrapper2("JVM_GetSockName (0x%x)", fd); //%note jvm_r6 - return hpi::get_sock_name(fd, him, len); + return os::get_sock_name(fd, him, len); JVM_END JVM_LEAF(jint, JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen)) JVMWrapper2("JVM_SendTo (0x%x)", fd); //%note jvm_r6 - return hpi::sendto(fd, buf, len, flags, to, tolen); + return os::sendto(fd, buf, len, flags, to, tolen); JVM_END JVM_LEAF(jint, JVM_SocketAvailable(jint fd, jint *pbytes)) JVMWrapper2("JVM_SocketAvailable (0x%x)", fd); //%note jvm_r6 - return hpi::socket_available(fd, pbytes); + return os::socket_available(fd, pbytes); JVM_END JVM_LEAF(jint, JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen)) JVMWrapper2("JVM_GetSockOpt (0x%x)", fd); //%note jvm_r6 - return hpi::get_sock_opt(fd, level, optname, optval, optlen); + return os::get_sock_opt(fd, level, optname, optval, optlen); JVM_END JVM_LEAF(jint, JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen)) JVMWrapper2("JVM_GetSockOpt (0x%x)", fd); //%note jvm_r6 - return hpi::set_sock_opt(fd, level, optname, optval, optlen); + return os::set_sock_opt(fd, level, optname, optval, optlen); JVM_END JVM_LEAF(int, JVM_GetHostName(char* name, int namelen)) JVMWrapper("JVM_GetHostName"); - return hpi::get_host_name(name, namelen); -JVM_END - -#ifdef _WINDOWS - -JVM_LEAF(struct hostent*, JVM_GetHostByAddr(const char* name, int len, int type)) - JVMWrapper("JVM_GetHostByAddr"); - return hpi::get_host_by_addr(name, len, type); -JVM_END - - -JVM_LEAF(struct hostent*, JVM_GetHostByName(char* name)) - JVMWrapper("JVM_GetHostByName"); - return hpi::get_host_by_name(name); -JVM_END - - -JVM_LEAF(struct protoent*, JVM_GetProtoByName(char* name)) - JVMWrapper("JVM_GetProtoByName"); - return hpi::get_proto_by_name(name); + return os::get_host_name(name, namelen); JVM_END -#endif - // Library support /////////////////////////////////////////////////////////////////////////// JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name)) @@ -3606,7 +3581,7 @@ JVM_ENTRY_NO_ENV(void*, JVM_LoadLibrary(const char* name)) void *load_result; { ThreadToNativeFromVM ttnfvm(thread); - load_result = hpi::dll_load(name, ebuf, sizeof ebuf); + load_result = os::dll_load(name, ebuf, sizeof ebuf); } if (load_result == NULL) { char msg[1024]; @@ -3628,13 +3603,13 @@ JVM_END JVM_LEAF(void, JVM_UnloadLibrary(void* handle)) JVMWrapper("JVM_UnloadLibrary"); - hpi::dll_unload(handle); + os::dll_unload(handle); JVM_END JVM_LEAF(void*, JVM_FindLibraryEntry(void* handle, const char* name)) JVMWrapper2("JVM_FindLibraryEntry (%s)", name); - return hpi::dll_lookup(handle, name); + return os::dll_lookup(handle, name); JVM_END // Floating point support //////////////////////////////////////////////////////////////////// diff --git a/src/share/vm/prims/jvm.h b/src/share/vm/prims/jvm.h index d8318cece0cd813b09f3167182f39913ee81fb9e..81816740724be483347a3147b34f5e471b24734c 100644 --- a/src/share/vm/prims/jvm.h +++ b/src/share/vm/prims/jvm.h @@ -27,7 +27,6 @@ #include "prims/jni.h" #include "runtime/reflectionCompat.hpp" -#include "utilities/globalDefinitions.hpp" #ifdef TARGET_OS_FAMILY_linux # include "jvm_linux.h" #endif @@ -1405,23 +1404,6 @@ JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen); JNIEXPORT jint JNICALL JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen); -/* - * These routines are only reentrant on Windows - */ - -#ifdef _WINDOWS - -JNIEXPORT struct protoent * JNICALL -JVM_GetProtoByName(char* name); - -JNIEXPORT struct hostent* JNICALL -JVM_GetHostByAddr(const char* name, int len, int type); - -JNIEXPORT struct hostent* JNICALL -JVM_GetHostByName(char* name); - -#endif /* _WINDOWS */ - JNIEXPORT int JNICALL JVM_GetHostName(char* name, int namelen); diff --git a/src/share/vm/prims/jvmti.xml b/src/share/vm/prims/jvmti.xml index 5e93bb36968bfac1d52876f6b46b8cec764e35b3..8d580294157976cddb8abaf54d1af139d615e06c 100644 --- a/src/share/vm/prims/jvmti.xml +++ b/src/share/vm/prims/jvmti.xml @@ -1,7 +1,7 @@