提交 66cf4a21 编写于 作者: T twisti

8008772: remove gamma launcher

Reviewed-by: kvn, neliasso, ctornqvi
上级 33d0b626
...@@ -151,32 +151,43 @@ else ...@@ -151,32 +151,43 @@ else
$(MAKE_ARGS) BUILD_FLAVOR=product docs $(MAKE_ARGS) BUILD_FLAVOR=product docs
endif endif
# Output directories
C1_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1
C2_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2
MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1
ZERO_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_zero
SHARK_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_shark
# Build variation of hotspot # Build variation of hotspot
$(C1_VM_TARGETS): $(C1_VM_TARGETS):
$(CD) $(GAMMADIR)/make; \ $(CD) $(GAMMADIR)/make; \
$(MAKE) BUILD_FLAVOR=$(@:%1=%) VM_TARGET=$@ generic_build1 $(ALT_OUT) $(MAKE) BUILD_DIR=$(C1_DIR) BUILD_FLAVOR=$(@:%1=%) VM_TARGET=$@ generic_build1 $(ALT_OUT)
$(C2_VM_TARGETS): $(C2_VM_TARGETS):
$(CD) $(GAMMADIR)/make; \ $(CD) $(GAMMADIR)/make; \
$(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) $(MAKE) BUILD_DIR=$(C2_DIR) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT)
$(ZERO_VM_TARGETS): $(ZERO_VM_TARGETS):
$(CD) $(GAMMADIR)/make; \ $(CD) $(GAMMADIR)/make; \
$(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ $(MAKE) BUILD_DIR=$(ZERO_DIR) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ generic_buildzero $(ALT_OUT)
generic_buildzero $(ALT_OUT)
$(SHARK_VM_TARGETS): $(SHARK_VM_TARGETS):
$(CD) $(GAMMADIR)/make; \ $(CD) $(GAMMADIR)/make; \
$(MAKE) BUILD_FLAVOR=$(@:%shark=%) VM_TARGET=$@ \ $(MAKE) BUILD_DIR=$(SHARK_DIR) BUILD_FLAVOR=$(@:%shark=%) VM_TARGET=$@ generic_buildshark $(ALT_OUT)
generic_buildshark $(ALT_OUT)
$(MINIMAL1_VM_TARGETS): $(MINIMAL1_VM_TARGETS):
$(CD) $(GAMMADIR)/make; \ $(CD) $(GAMMADIR)/make; \
$(MAKE) BUILD_FLAVOR=$(@:%minimal1=%) VM_TARGET=$@ \ $(MAKE) BUILD_DIR=$(MINIMAL1_DIR) BUILD_FLAVOR=$(@:%minimal1=%) VM_TARGET=$@ generic_buildminimal1 $(ALT_OUT)
generic_buildminimal1 $(ALT_OUT)
# Install hotspot script in build directory
HOTSPOT_SCRIPT=$(BUILD_DIR)/$(BUILD_FLAVOR)/hotspot
$(HOTSPOT_SCRIPT): $(GAMMADIR)/make/hotspot.script
$(QUIETLY) $(MKDIR) -p $(BUILD_DIR)/$(BUILD_FLAVOR)
$(QUIETLY) cat $< | sed -e 's|@@LIBARCH@@|$(LIBARCH)|g' | sed -e 's|@@JDK_IMPORT_PATH@@|$(JDK_IMPORT_PATH)|g' > $@
$(QUIETLY) chmod +x $@
# Build compiler1 (client) rule, different for platforms # Build compiler1 (client) rule, different for platforms
generic_build1: generic_build1: $(HOTSPOT_SCRIPT)
$(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)
ifeq ($(OSNAME),windows) ifeq ($(OSNAME),windows)
ifeq ($(ARCH_DATA_MODEL), 32) ifeq ($(ARCH_DATA_MODEL), 32)
...@@ -201,7 +212,7 @@ else ...@@ -201,7 +212,7 @@ else
endif endif
# Build compiler2 (server) rule, different for platforms # Build compiler2 (server) rule, different for platforms
generic_build2: generic_build2: $(HOTSPOT_SCRIPT)
$(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)
ifeq ($(OSNAME),windows) ifeq ($(OSNAME),windows)
$(CD) $(OUTPUTDIR); \ $(CD) $(OUTPUTDIR); \
...@@ -217,19 +228,19 @@ else ...@@ -217,19 +228,19 @@ else
$(MAKE_ARGS) $(VM_TARGET) $(MAKE_ARGS) $(VM_TARGET)
endif endif
generic_buildzero: generic_buildzero: $(HOTSPOT_SCRIPT)
$(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)
$(CD) $(OUTPUTDIR); \ $(CD) $(OUTPUTDIR); \
$(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE) -f $(ABS_OS_MAKEFILE) \
$(MAKE_ARGS) $(VM_TARGET) $(MAKE_ARGS) $(VM_TARGET)
generic_buildshark: generic_buildshark: $(HOTSPOT_SCRIPT)
$(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)
$(CD) $(OUTPUTDIR); \ $(CD) $(OUTPUTDIR); \
$(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE) -f $(ABS_OS_MAKEFILE) \
$(MAKE_ARGS) $(VM_TARGET) $(MAKE_ARGS) $(VM_TARGET)
generic_buildminimal1: generic_buildminimal1: $(HOTSPOT_SCRIPT)
ifeq ($(JVM_VARIANT_MINIMAL1),true) ifeq ($(JVM_VARIANT_MINIMAL1),true)
$(MKDIR) -p $(OUTPUTDIR) $(MKDIR) -p $(OUTPUTDIR)
ifeq ($(ARCH_DATA_MODEL), 32) ifeq ($(ARCH_DATA_MODEL), 32)
...@@ -252,224 +263,210 @@ endif ...@@ -252,224 +263,210 @@ endif
# Export file rule # Export file rule
generic_export: $(EXPORT_LIST) generic_export: $(EXPORT_LIST)
export_product: export_product:
$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%=%) generic_export
generic_export
export_fastdebug: export_fastdebug:
$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export
EXPORT_SUBDIR=/$(@:export_%=%) \
generic_export
export_debug: export_debug:
$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export
EXPORT_SUBDIR=/$(@:export_%=%) \
generic_export
export_optimized: export_optimized:
$(MAKE) BUILD_FLAVOR=$(@:export_%=%) VM_SUBDIR=$(@:export_%=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%=%) EXPORT_SUBDIR=/$(@:export_%=%) generic_export
EXPORT_SUBDIR=/$(@:export_%=%) \
generic_export
export_product_jdk:: export_product_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
generic_export
export_optimized_jdk:: export_optimized_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) generic_export
VM_SUBDIR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \
generic_export
export_fastdebug_jdk:: export_fastdebug_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
VM_SUBDIR=$(@:export_%_jdk=%) \
ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \
generic_export
export_debug_jdk:: export_debug_jdk::
$(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) VM_SUBDIR=$(@:export_%_jdk=%) \ $(MAKE) BUILD_FLAVOR=$(@:export_%_jdk=%) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) generic_export
ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/$(@:export_%_jdk=%) \
generic_export
# Export file copy rules # Export file copy rules
XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt
DOCS_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_docs DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs
C1_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1/$(VM_SUBDIR) C1_BUILD_DIR =$(C1_DIR)/$(BUILD_FLAVOR)
C2_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2/$(VM_SUBDIR) C2_BUILD_DIR =$(C2_DIR)/$(BUILD_FLAVOR)
MINIMAL1_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1/$(VM_SUBDIR) MINIMAL1_BUILD_DIR=$(MINIMAL1_DIR)/$(BUILD_FLAVOR)
ZERO_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_zero/$(VM_SUBDIR) ZERO_BUILD_DIR =$(ZERO_DIR)/$(BUILD_FLAVOR)
SHARK_DIR =$(OUTPUTDIR)/$(VM_PLATFORM)_shark/$(VM_SUBDIR) SHARK_BUILD_DIR =$(SHARK_DIR)/$(BUILD_FLAVOR)
# Server (C2) # Server (C2)
ifeq ($(JVM_VARIANT_SERVER), true) ifeq ($(JVM_VARIANT_SERVER), true)
# Common # Common
$(EXPORT_SERVER_DIR)/%.diz: $(C2_DIR)/%.diz $(EXPORT_SERVER_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.jar: $(C2_DIR)/../generated/%.jar $(EXPORT_LIB_DIR)/%.jar: $(C2_BUILD_DIR)/../generated/%.jar
$(install-file) $(install-file)
$(EXPORT_INCLUDE_DIR)/%: $(C2_DIR)/../generated/jvmtifiles/% $(EXPORT_INCLUDE_DIR)/%: $(C2_BUILD_DIR)/../generated/jvmtifiles/%
$(install-file) $(install-file)
# Windows # Windows
$(EXPORT_SERVER_DIR)/%.dll: $(C2_DIR)/%.dll $(EXPORT_SERVER_DIR)/%.dll: $(C2_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.pdb: $(C2_DIR)/%.pdb $(EXPORT_SERVER_DIR)/%.pdb: $(C2_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map $(EXPORT_SERVER_DIR)/%.map: $(C2_BUILD_DIR)/%.map
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.lib: $(C2_DIR)/%.lib $(EXPORT_LIB_DIR)/%.lib: $(C2_BUILD_DIR)/%.lib
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.diz: $(C2_DIR)/%.diz $(EXPORT_JRE_BIN_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.dll: $(C2_DIR)/%.dll $(EXPORT_JRE_BIN_DIR)/%.dll: $(C2_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C2_DIR)/%.pdb $(EXPORT_JRE_BIN_DIR)/%.pdb: $(C2_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.map: $(C2_DIR)/%.map $(EXPORT_JRE_BIN_DIR)/%.map: $(C2_BUILD_DIR)/%.map
$(install-file) $(install-file)
# Unix # Unix
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(C2_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_DIR)/%.debuginfo $(EXPORT_SERVER_DIR)/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_DIR)/%.debuginfo $(EXPORT_SERVER_DIR)/64/%.debuginfo: $(C2_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C2_DIR)/%.diz $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C2_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/64/%.diz: $(C2_DIR)/%.diz $(EXPORT_SERVER_DIR)/64/%.diz: $(C2_BUILD_DIR)/%.diz
$(install-file) $(install-file)
endif endif
# Client (C1) # Client (C1)
ifeq ($(JVM_VARIANT_CLIENT), true) ifeq ($(JVM_VARIANT_CLIENT), true)
# Common # Common
$(EXPORT_CLIENT_DIR)/%.diz: $(C1_DIR)/%.diz $(EXPORT_CLIENT_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.jar: $(C1_DIR)/../generated/%.jar $(EXPORT_LIB_DIR)/%.jar: $(C1_BUILD_DIR)/../generated/%.jar
$(install-file) $(install-file)
$(EXPORT_INCLUDE_DIR)/%: $(C1_DIR)/../generated/jvmtifiles/% $(EXPORT_INCLUDE_DIR)/%: $(C1_BUILD_DIR)/../generated/jvmtifiles/%
$(install-file) $(install-file)
# Windows # Windows
$(EXPORT_CLIENT_DIR)/%.dll: $(C1_DIR)/%.dll $(EXPORT_CLIENT_DIR)/%.dll: $(C1_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/%.pdb: $(C1_DIR)/%.pdb $(EXPORT_CLIENT_DIR)/%.pdb: $(C1_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/%.map: $(C1_DIR)/%.map $(EXPORT_CLIENT_DIR)/%.map: $(C1_BUILD_DIR)/%.map
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.lib: $(C1_DIR)/%.lib $(EXPORT_LIB_DIR)/%.lib: $(C1_BUILD_DIR)/%.lib
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.diz: $(C1_DIR)/%.diz $(EXPORT_JRE_BIN_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.dll: $(C1_DIR)/%.dll $(EXPORT_JRE_BIN_DIR)/%.dll: $(C1_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.pdb: $(C1_DIR)/%.pdb $(EXPORT_JRE_BIN_DIR)/%.pdb: $(C1_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.map: $(C1_DIR)/%.map $(EXPORT_JRE_BIN_DIR)/%.map: $(C1_BUILD_DIR)/%.map
$(install-file) $(install-file)
# Unix # Unix
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_CLIENT_DIR)/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_CLIENT_DIR)/64/%.$(LIBRARY_SUFFIX): $(C1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_DIR)/%.debuginfo $(EXPORT_CLIENT_DIR)/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_DIR)/%.debuginfo $(EXPORT_CLIENT_DIR)/64/%.debuginfo: $(C1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C1_DIR)/%.diz $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(C1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_CLIENT_DIR)/64/%.diz: $(C1_DIR)/%.diz $(EXPORT_CLIENT_DIR)/64/%.diz: $(C1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
endif endif
# Minimal1 # Minimal1
ifeq ($(JVM_VARIANT_MINIMAL1), true) ifeq ($(JVM_VARIANT_MINIMAL1), true)
# Common # Common
$(EXPORT_MINIMAL_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz $(EXPORT_MINIMAL_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.jar: $(MINIMAL1_DIR)/../generated/%.jar $(EXPORT_LIB_DIR)/%.jar: $(MINIMAL1_BUILD_DIR)/../generated/%.jar
$(install-file) $(install-file)
$(EXPORT_INCLUDE_DIR)/%: $(MINIMAL1_DIR)/../generated/jvmtifiles/% $(EXPORT_INCLUDE_DIR)/%: $(MINIMAL1_BUILD_DIR)/../generated/jvmtifiles/%
$(install-file) $(install-file)
# Windows # Windows
$(EXPORT_MINIMAL_DIR)/%.dll: $(MINIMAL1_DIR)/%.dll $(EXPORT_MINIMAL_DIR)/%.dll: $(MINIMAL1_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/%.pdb: $(MINIMAL1_DIR)/%.pdb $(EXPORT_MINIMAL_DIR)/%.pdb: $(MINIMAL1_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/%.map: $(MINIMAL1_DIR)/%.map $(EXPORT_MINIMAL_DIR)/%.map: $(MINIMAL1_BUILD_DIR)/%.map
$(install-file) $(install-file)
$(EXPORT_LIB_DIR)/%.lib: $(MINIMAL1_DIR)/%.lib $(EXPORT_LIB_DIR)/%.lib: $(MINIMAL1_BUILD_DIR)/%.lib
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz $(EXPORT_JRE_BIN_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.dll: $(MINIMAL1_DIR)/%.dll $(EXPORT_JRE_BIN_DIR)/%.dll: $(MINIMAL1_BUILD_DIR)/%.dll
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.pdb: $(MINIMAL1_DIR)/%.pdb $(EXPORT_JRE_BIN_DIR)/%.pdb: $(MINIMAL1_BUILD_DIR)/%.pdb
$(install-file) $(install-file)
$(EXPORT_JRE_BIN_DIR)/%.map: $(MINIMAL1_DIR)/%.map $(EXPORT_JRE_BIN_DIR)/%.map: $(MINIMAL1_BUILD_DIR)/%.map
$(install-file) $(install-file)
# Unix # Unix
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_MINIMAL_DIR)/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/64/%.$(LIBRARY_SUFFIX): $(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_MINIMAL_DIR)/64/%.$(LIBRARY_SUFFIX): $(MINIMAL1_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo $(EXPORT_MINIMAL_DIR)/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/64/%.debuginfo: $(MINIMAL1_DIR)/%.debuginfo $(EXPORT_MINIMAL_DIR)/64/%.debuginfo: $(MINIMAL1_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(MINIMAL1_DIR)/%.diz $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_MINIMAL_DIR)/64/%.diz: $(MINIMAL1_DIR)/%.diz $(EXPORT_MINIMAL_DIR)/64/%.diz: $(MINIMAL1_BUILD_DIR)/%.diz
$(install-file) $(install-file)
endif endif
# Zero # Zero
ifeq ($(JVM_VARIANT_ZERO), true) ifeq ($(JVM_VARIANT_ZERO), true)
# Common # Common
$(EXPORT_LIB_DIR)/%.jar: $(ZERO_DIR)/../generated/%.jar $(EXPORT_LIB_DIR)/%.jar: $(ZERO_BUILD_DIR)/../generated/%.jar
$(install-file) $(install-file)
$(EXPORT_INCLUDE_DIR)/%: $(ZERO_DIR)/../generated/jvmtifiles/% $(EXPORT_INCLUDE_DIR)/%: $(ZERO_BUILD_DIR)/../generated/jvmtifiles/%
$(install-file) $(install-file)
# Unix # Unix
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(ZERO_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_DIR)/%.diz $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(ZERO_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_DIR)/%.debuginfo $(EXPORT_SERVER_DIR)/%.debuginfo: $(ZERO_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.diz: $(ZERO_DIR)/%.diz $(EXPORT_SERVER_DIR)/%.diz: $(ZERO_BUILD_DIR)/%.diz
$(install-file) $(install-file)
endif endif
# Shark # Shark
ifeq ($(JVM_VARIANT_ZEROSHARK), true) ifeq ($(JVM_VARIANT_ZEROSHARK), true)
# Common # Common
$(EXPORT_LIB_DIR)/%.jar: $(SHARK_DIR)/../generated/%.jar $(EXPORT_LIB_DIR)/%.jar: $(SHARK_BUILD_DIR)/../generated/%.jar
$(install-file) $(install-file)
$(EXPORT_INCLUDE_DIR)/%: $(SHARK_DIR)/../generated/jvmtifiles/% $(EXPORT_INCLUDE_DIR)/%: $(SHARK_BUILD_DIR)/../generated/jvmtifiles/%
$(install-file) $(install-file)
# Unix # Unix
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_DIR)/%.debuginfo $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo): $(SHARK_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_DIR)/%.diz $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(SHARK_BUILD_DIR)/%.diz
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX) $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_BUILD_DIR)/%.$(LIBRARY_SUFFIX)
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_DIR)/%.debuginfo $(EXPORT_SERVER_DIR)/%.debuginfo: $(SHARK_BUILD_DIR)/%.debuginfo
$(install-file) $(install-file)
$(EXPORT_SERVER_DIR)/%.diz: $(SHARK_DIR)/%.diz $(EXPORT_SERVER_DIR)/%.diz: $(SHARK_BUILD_DIR)/%.diz
$(install-file) $(install-file)
endif endif
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
# adlc.make - # adlc.make -
# jvmti.make - generate JVMTI bindings from the spec (JSR-163) # jvmti.make - generate JVMTI bindings from the spec (JSR-163)
# sa.make - generate SA jar file and natives # sa.make - generate SA jar file and natives
# env.[ck]sh - environment settings
# #
# The makefiles are split this way so that "make foo" will run faster by not # The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm. # having to read the dependency files for the vm.
...@@ -129,9 +128,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) ...@@ -129,9 +128,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
# dtrace.make is used on BSD versions that implement Dtrace (like MacOS X) # dtrace.make is used on BSD versions that implement Dtrace (like MacOS X)
BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make \ BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make dtrace.make
jvmti.make sa.make dtrace.make \
env.sh env.csh jdkpath.sh
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
...@@ -354,33 +351,6 @@ dtrace.make: $(BUILDTREE_MAKE) ...@@ -354,33 +351,6 @@ dtrace.make: $(BUILDTREE_MAKE)
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
) > $@ ) > $@
env.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
{ \
echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
) > $@
env.csh: env.sh
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
) > $@
jdkpath.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
echo "JDK=${JAVA_HOME}"; \
) > $@
FORCE: FORCE:
.PHONY: all FORCE .PHONY: all FORCE
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# Rules to build gamma launcher, used by vm.make
LAUNCHER_SCRIPT = hotspot
LAUNCHER = gamma
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) \
$(TARGET_DEFINES)
# Give the launcher task_for_pid() privileges so that it can be used to run JStack, JInfo, et al.
LFLAGS_LAUNCHER += -sectcreate __TEXT __info_plist $(GAMMADIR)/src/os/bsd/launcher/Info-privileged.plist
ifeq ($(LINK_INTO),AOUT)
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
LAUNCHER_MAPFILE = mapfile_reorder
LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE))
LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC)
LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS)
else
LAUNCHER.o = launcher.o
LFLAGS_LAUNCHER += -L`pwd`
# The gamma launcher runs the JDK from $JAVA_HOME, overriding the JVM with a
# freshly built JVM at ./libjvm.{so|dylib}. This is accomplished by setting
# the library searchpath using ({DY}LD_LIBRARY_PATH) to find the local JVM
# first. Gamma dlopen()s libjava from $JAVA_HOME/jre/lib{/$arch}, which is
# statically linked with CoreFoundation framework libs. Unfortunately, gamma's
# unique searchpath results in some unresolved symbols in the framework
# libraries, because JDK libraries are inadvertently discovered first on the
# searchpath, e.g. libjpeg. On Mac OS X, filenames are case *insensitive*.
# So, the actual filename collision is libjpeg.dylib and libJPEG.dylib.
# To resolve this, gamma needs to also statically link with the CoreFoundation
# framework libraries.
ifeq ($(OS_VENDOR),Darwin)
LFLAGS_LAUNCHER += -framework CoreFoundation
endif
LIBS_LAUNCHER += -l$(JVM) $(LIBS)
endif
LINK_LAUNCHER = $(LINK.CC)
LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK)
LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK)
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) $(CXXFLAGS)
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS)
$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
$(QUIETLY) echo Linking launcher...
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(OBJS)) $(LIBS_LAUNCHER)
$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
# Sign the launcher with the development certificate (if present) so that it can be used
# to run JStack, JInfo, et al.
$(QUIETLY) -codesign -s openjdk_codesign $@
$(LAUNCHER): $(LAUNCHER_SCRIPT)
$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
$(QUIETLY) chmod +x $@
...@@ -328,9 +328,6 @@ install_jvm: $(LIBJVM) ...@@ -328,9 +328,6 @@ install_jvm: $(LIBJVM)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Other files # Other files
# Gamma launcher
include $(MAKEFILES_DIR)/launcher.make
# Signal interposition library # Signal interposition library
include $(MAKEFILES_DIR)/jsig.make include $(MAKEFILES_DIR)/jsig.make
......
...@@ -72,6 +72,7 @@ EMACS=emacs ...@@ -72,6 +72,7 @@ EMACS=emacs
REL_MYDIR=`dirname $0` REL_MYDIR=`dirname $0`
MYDIR=`cd $REL_MYDIR && pwd` MYDIR=`cd $REL_MYDIR && pwd`
#
# Look whether the user wants to run inside gdb # Look whether the user wants to run inside gdb
case "$1" in case "$1" in
-gdb) -gdb)
...@@ -95,16 +96,14 @@ case "$1" in ...@@ -95,16 +96,14 @@ case "$1" in
;; ;;
esac esac
JDK= if [ "${ALT_JAVA_HOME}" != "" ]; then
if [ "${ALT_JAVA_HOME}" = "" ]; then JDK=${ALT_JAVA_HOME%%/jre}
. ${MYDIR}/jdkpath.sh
else else
JDK=${ALT_JAVA_HOME%%/jre}; JDK=@@JDK_IMPORT_PATH@@
fi fi
if [ "${JDK}" = "" ]; then if [ "${JDK}" = "" ]; then
echo Failed to find JDK. ALT_JAVA_HOME is not set or ./jdkpath.sh is empty or not found. echo "Failed to find JDK. Either ALT_JAVA_HOME is not set or JDK_IMPORT_PATH is empty."
exit 1
fi fi
# We will set the LD_LIBRARY_PATH as follows: # We will set the LD_LIBRARY_PATH as follows:
...@@ -142,12 +141,12 @@ else ...@@ -142,12 +141,12 @@ else
export LD_LIBRARY_PATH export LD_LIBRARY_PATH
fi fi
JPARMS="$@ $JAVA_ARGS"; JPARMS="-Dsun.java.launcher=gamma -XXaltjvm=$MYDIR $@ $JAVA_ARGS";
# Locate the gamma development launcher # Locate the java launcher
LAUNCHER=${MYDIR}/gamma LAUNCHER=$JDK/bin/java
if [ ! -x $LAUNCHER ] ; then if [ ! -x $LAUNCHER ] ; then
echo Error: Cannot find the gamma development launcher \"$LAUNCHER\" echo Error: Cannot find the java launcher \"$LAUNCHER\"
exit 1 exit 1
fi fi
...@@ -166,9 +165,10 @@ set args $JPARMS ...@@ -166,9 +165,10 @@ set args $JPARMS
file $LAUNCHER file $LAUNCHER
directory $GDBSRCDIR directory $GDBSRCDIR
# Get us to a point where we can set breakpoints in libjvm.so # Get us to a point where we can set breakpoints in libjvm.so
break InitializeJVM set breakpoint pending on
break JNI_CreateJavaVM
run run
# Stop in InitializeJVM # Stop in JNI_CreateJavaVM
delete 1 delete 1
# We can now set breakpoints wherever we like # We can now set breakpoints wherever we like
EOF EOF
...@@ -199,7 +199,7 @@ case "$MODE" in ...@@ -199,7 +199,7 @@ case "$MODE" in
rm -f $GDBSCR rm -f $GDBSCR
;; ;;
dbx) dbx)
$DBX -s $HOME/.dbxrc $LAUNCHER $JPARMS $DBX -s $HOME/.dbxrc -c "loadobject -load libjvm.so; stop in JNI_CreateJavaVM; run $JPARMS; delete all" $LAUNCHER
;; ;;
valgrind) valgrind)
echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap echo Warning: Defaulting to 16Mb heap to make Valgrind run faster, use -Xmx for larger heap
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
# adlc.make - # adlc.make -
# jvmti.make - generate JVMTI bindings from the spec (JSR-163) # jvmti.make - generate JVMTI bindings from the spec (JSR-163)
# sa.make - generate SA jar file and natives # sa.make - generate SA jar file and natives
# env.[ck]sh - environment settings
# #
# The makefiles are split this way so that "make foo" will run faster by not # The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm. # having to read the dependency files for the vm.
...@@ -123,8 +122,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) ...@@ -123,8 +122,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
# For dependencies and recursive makes. # For dependencies and recursive makes.
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make
env.sh env.csh jdkpath.sh
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) SRCARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
...@@ -349,33 +347,6 @@ sa.make: $(BUILDTREE_MAKE) ...@@ -349,33 +347,6 @@ sa.make: $(BUILDTREE_MAKE)
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
) > $@ ) > $@
env.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
{ \
echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
) > $@
env.csh: env.sh
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
) > $@
jdkpath.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
echo "JDK=${JAVA_HOME}"; \
) > $@
FORCE: FORCE:
.PHONY: all FORCE .PHONY: all FORCE
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# Rules to build gamma launcher, used by vm.make
LAUNCHER_SCRIPT = hotspot
LAUNCHER = gamma
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) \
$(TARGET_DEFINES)
ifeq ($(LINK_INTO),AOUT)
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
LAUNCHER_MAPFILE = mapfile_reorder
LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE))
LFLAGS_LAUNCHER += $(SONAMEFLAG:SONAME=$(LIBJVM)) $(STATIC_LIBGCC)
LIBS_LAUNCHER += $(STATIC_STDCXX) $(LIBS)
else
LAUNCHER.o = launcher.o
LFLAGS_LAUNCHER += -L `pwd`
LIBS_LAUNCHER += -l$(JVM) $(LIBS)
endif
LINK_LAUNCHER = $(LINK.CC)
LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK)
LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK)
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) $(CXXFLAGS)
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS)
$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
$(QUIETLY) echo Linking launcher...
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(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 $@
...@@ -372,9 +372,6 @@ install_jvm: $(LIBJVM) ...@@ -372,9 +372,6 @@ install_jvm: $(LIBJVM)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Other files # Other files
# Gamma launcher
include $(MAKEFILES_DIR)/launcher.make
# Signal interposition library # Signal interposition library
include $(MAKEFILES_DIR)/jsig.make include $(MAKEFILES_DIR)/jsig.make
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
# adlc.make - # adlc.make -
# jvmti.make - generate JVMTI bindings from the spec (JSR-163) # jvmti.make - generate JVMTI bindings from the spec (JSR-163)
# sa.make - generate SA jar file and natives # sa.make - generate SA jar file and natives
# env.[ck]sh - environment settings
# #
# The makefiles are split this way so that "make foo" will run faster by not # The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm. # having to read the dependency files for the vm.
...@@ -116,8 +115,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS)) ...@@ -116,8 +115,7 @@ SUBMAKE_DIRS = $(addprefix $(PLATFORM_DIR)/,$(TARGETS))
# For dependencies and recursive makes. # For dependencies and recursive makes.
BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make BUILDTREE_MAKE = $(GAMMADIR)/make/$(OS_FAMILY)/makefiles/buildtree.make
BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make \ BUILDTREE_TARGETS = Makefile flags.make flags_vm.make vm.make adlc.make jvmti.make sa.make
env.sh env.csh jdkpath.sh
BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \ BUILDTREE_VARS = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OS_FAMILY) \
ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT) ARCH=$(ARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH) VARIANT=$(VARIANT)
...@@ -339,33 +337,6 @@ sa.make: $(BUILDTREE_MAKE) ...@@ -339,33 +337,6 @@ sa.make: $(BUILDTREE_MAKE)
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \ echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(@F)"; \
) > $@ ) > $@
env.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "JAVA_HOME=$(JDK_IMPORT_PATH)"; }; \
{ \
echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \
} | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \
echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \
echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \
) > $@
env.csh: env.sh
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
{ echo "setenv JAVA_HOME \"$(JDK_IMPORT_PATH)\""; }; \
sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=/setenv \1 /p' $?; \
) > $@
jdkpath.sh: $(BUILDTREE_MAKE)
@echo Creating $@ ...
$(QUIETLY) ( \
$(BUILDTREE_COMMENT); \
echo "JDK=${JAVA_HOME}"; \
) > $@
FORCE: FORCE:
.PHONY: all FORCE .PHONY: all FORCE
#
# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
# Rules to build gamma launcher, used by vm.make
LAUNCHER_SCRIPT = hotspot
LAUNCHER = gamma
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) \
$(TARGET_DEFINES)
ifeq ($(LINK_INTO),AOUT)
LAUNCHER.o = launcher.o $(JVM_OBJ_FILES)
LAUNCHER_MAPFILE = mapfile_extended
LFLAGS_LAUNCHER$(LDNOMAP) += $(MAPFLAG:FILENAME=$(LAUNCHER_MAPFILE))
LIBS_LAUNCHER += $(LIBS)
else
LAUNCHER.o = launcher.o
LFLAGS_LAUNCHER += -L `pwd`
LIBS_LAUNCHER += -l$(JVM) $(LIBS)
endif
LINK_LAUNCHER = $(LINK.CXX)
LINK_LAUNCHER/PRE_HOOK = $(LINK_LIB.CXX/PRE_HOOK)
LINK_LAUNCHER/POST_HOOK = $(LINK_LIB.CXX/POST_HOOK)
ifeq ("${Platform_compiler}", "sparcWorks")
# Enable the following LAUNCHERFLAGS addition if you need to compare the
# built ELF objects.
#
# The -g option makes static data global and the "-W0,-noglobal"
# option tells the compiler to not globalize static data using a unique
# globalization prefix. Instead force the use of a static globalization
# prefix based on the source filepath so the objects from two identical
# compilations are the same.
#
# Note: The blog says to use "-W0,-xglobalstatic", but that doesn't
# seem to work. I got "-W0,-noglobal" from Kelly and that works.
#LAUNCHERFLAGS += -W0,-noglobal
endif # Platform_compiler == sparcWorks
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) $(CXXFLAGS)
$(LAUNCHER_OUT)/%.o: $(LAUNCHERDIR)/%.c
$(QUIETLY) [ -d $(LAUNCHER_OUT) ] || { mkdir -p $(LAUNCHER_OUT); }
$(QUIETLY) $(CC) -g -o $@ -c $< -MMD $(LAUNCHERFLAGS) $(CXXFLAGS)
$(LAUNCHER): $(OBJS) $(LIBJVM) $(LAUNCHER_MAPFILE)
ifeq ($(filter -sbfast -xsbfast, $(CFLAGS_BROWSE)),)
$(QUIETLY) echo Linking launcher...
$(QUIETLY) $(LINK_LAUNCHER/PRE_HOOK)
$(QUIETLY) $(LINK_LAUNCHER) $(LFLAGS_LAUNCHER) -o $@ $(sort $(OBJS)) $(LIBS_LAUNCHER)
$(QUIETLY) $(LINK_LAUNCHER/POST_HOOK)
endif # filter -sbfast -xsbfast
$(LAUNCHER): $(LAUNCHER_SCRIPT)
$(LAUNCHER_SCRIPT): $(LAUNCHERDIR)/launcher.script
$(QUIETLY) sed -e 's/@@LIBARCH@@/$(LIBARCH)/g' $< > $@
$(QUIETLY) chmod +x $@
...@@ -338,9 +338,6 @@ install_jvm: $(LIBJVM) ...@@ -338,9 +338,6 @@ install_jvm: $(LIBJVM)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Other files # Other files
# Gamma launcher
include $(MAKEFILES_DIR)/launcher.make
# Signal interposition library # Signal interposition library
include $(MAKEFILES_DIR)/jsig.make include $(MAKEFILES_DIR)/jsig.make
......
...@@ -33,7 +33,7 @@ GENERATED=../generated ...@@ -33,7 +33,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj BUILD_PCH_FILE=_build_pch_file.obj
!endif !endif
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
!include ../local.make !include ../local.make
!include compile.make !include compile.make
...@@ -71,4 +71,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def ...@@ -71,4 +71,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make
!include $(WorkSpace)/make/windows/makefiles/launcher.make
...@@ -33,7 +33,7 @@ GENERATED=../generated ...@@ -33,7 +33,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj BUILD_PCH_FILE=_build_pch_file.obj
!endif !endif
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
!include ../local.make !include ../local.make
!include compile.make !include compile.make
...@@ -70,4 +70,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def ...@@ -70,4 +70,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make
!include $(WorkSpace)/make/windows/makefiles/launcher.make
#
# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please 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=$(CXX_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 \
/I $(WorkSpace)\src\share\vm\prims \
/I $(WorkSpace)\src\share\vm \
/I $(WorkSpace)\src\cpu\$(Platform_arch)\vm \
/I $(WorkSpace)\src\os\windows\vm
LD_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
LD_FLAGS = $(LD_FLAGS) $(BUFFEROVERFLOWLIB)
!endif
!if "$(COMPILER_NAME)" == "VS2010" && "$(BUILDARCH)" == "i486"
LD_FLAGS = /SAFESEH $(LD_FLAGS)
!endif
LAUNCHERDIR = $(WorkSpace)/src/os/windows/launcher
LAUNCHERDIR_SHARE = $(WorkSpace)/src/share/tools/launcher
OUTDIR = launcher
{$(LAUNCHERDIR)}.c{$(OUTDIR)}.obj:
-mkdir $(OUTDIR) 2>NUL >NUL
$(CXX) $(LAUNCHER_FLAGS) /c /Fo$@ $<
{$(LAUNCHERDIR_SHARE)}.c{$(OUTDIR)}.obj:
-mkdir $(OUTDIR) 2>NUL >NUL
$(CXX) $(LAUNCHER_FLAGS) /c /Fo$@ $<
$(OUTDIR)\*.obj: $(LAUNCHERDIR)\*.c $(LAUNCHERDIR)\*.h $(LAUNCHERDIR_SHARE)\*.c $(LAUNCHERDIR_SHARE)\*.h
launcher: $(OUTDIR)\java.obj $(OUTDIR)\java_md.obj $(OUTDIR)\jli_util.obj
echo $(JAVA_HOME) > jdkpath.txt
$(LD) $(LD_FLAGS) /out:hotspot.exe $**
...@@ -32,7 +32,7 @@ GENERATED=../generated ...@@ -32,7 +32,7 @@ GENERATED=../generated
BUILD_PCH_FILE=_build_pch_file.obj BUILD_PCH_FILE=_build_pch_file.obj
!endif !endif
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA default:: $(BUILD_PCH_FILE) $(AOUT) checkAndBuildSA
!include ../local.make !include ../local.make
!include compile.make !include compile.make
...@@ -73,4 +73,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def ...@@ -73,4 +73,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
!include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/shared.make
!include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/sa.make
!include $(WorkSpace)/make/windows/makefiles/launcher.make
...@@ -59,7 +59,6 @@ ProjectCreatorIncludesPRIVATE=\ ...@@ -59,7 +59,6 @@ ProjectCreatorIncludesPRIVATE=\
-relativeSrcInclude src \ -relativeSrcInclude src \
-absoluteSrcInclude $(HOTSPOTBUILDSPACE) \ -absoluteSrcInclude $(HOTSPOTBUILDSPACE) \
-ignorePath $(HOTSPOTBUILDSPACE) \ -ignorePath $(HOTSPOTBUILDSPACE) \
-ignorePath launcher \
-ignorePath share\vm\adlc \ -ignorePath share\vm\adlc \
-ignorePath share\vm\shark \ -ignorePath share\vm\shark \
-ignorePath share\tools \ -ignorePath share\tools \
...@@ -105,7 +104,6 @@ ProjectCreatorIDEOptions=\ ...@@ -105,7 +104,6 @@ ProjectCreatorIDEOptions=\
-define ALIGN_STACK_FRAMES \ -define ALIGN_STACK_FRAMES \
-define VM_LITTLE_ENDIAN \ -define VM_LITTLE_ENDIAN \
-prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LD_VER)" \ -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LD_VER)" \
-postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \
-ignoreFile jsig.c \ -ignoreFile jsig.c \
-ignoreFile jvmtiEnvRecommended.cpp \ -ignoreFile jvmtiEnvRecommended.cpp \
-ignoreFile jvmtiEnvStub.cpp \ -ignoreFile jvmtiEnvStub.cpp \
......
...@@ -65,7 +65,6 @@ JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles ...@@ -65,7 +65,6 @@ JvmtiOutDir=$(HOTSPOTBUILDSPACE)\$(Variant)\generated\jvmtifiles
!endif !endif
HS_INTERNAL_NAME=jvm HS_INTERNAL_NAME=jvm
!include $(HOTSPOTWORKSPACE)/make/windows/makefiles/launcher.make
default:: $(AdditionalTargets) $(JvmtiGeneratedFiles) default:: $(AdditionalTargets) $(JvmtiGeneratedFiles)
......
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "java.h"
#include <dirent.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#ifndef GAMMA
#include "manifest_info.h"
#include "version_comp.h"
#endif
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
#include <pthread.h>
#else
#include <thread.h>
#endif
#ifdef __APPLE__
#define JVM_DLL "libjvm.dylib"
#define JAVA_DLL "libjava.dylib"
#define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH"
#else
#define JVM_DLL "libjvm.so"
#define JAVA_DLL "libjava.so"
#define LD_LIBRARY_PATH "LD_LIBRARY_PATH"
#endif
#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 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.
*/
#ifndef LIBARCHNAME
# error "The macro LIBARCHNAME was not defined on the compile line"
#endif
#ifdef __sun
# define DUAL_MODE
# 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 <sys/systeminfo.h>
# include <sys/elf.h>
# include <stdio.h>
#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);
#ifndef GAMMA
const char *
GetArch()
{
return LIBARCHNAME;
}
#endif /* ifndef GAMMA */
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 **)JLI_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)?LIBARCH64NAME:LIBARCH32NAME), JNI_TRUE)) {
goto EndDataModelSpeculate;
}
/*
* Read in jvm.cfg for target data model and process vm
* selection options.
*/
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)?LIBARCH64NAME:LIBARCH32NAME));
}
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/$LIBARCHNAME
* o $JRE/../lib/$LIBARCHNAME
*
* 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 */
#if defined(__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;
}
#elif defined(_ALLBSD_SOURCE)
/*
* On BSD, if a binary is running as sgid or suid, libc 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(issetugid()) {
return;
}
#endif
/* runpath contains current effective LD_LIBRARY_PATH setting */
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 "=");
/*
* 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)?"/"LIBARCH64NAME:"/.."):""), */
sprintf(new_runpath, LD_LIBRARY_PATH "="
"%s:"
"%s/lib/%s:"
"%s/../lib/%s",
jvmpath,
#ifdef DUAL_MODE
jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME),
jrepath, ((wanted==64)?LIBARCH64NAME:LIBARCH32NAME)
#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/LIBARCH64NAME/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(JLI_MemAlloc(strlen(execname) + 1), execname);
char *olddir = oldexec;
char *oldbase = strrchr(oldexec, '/');
newexec = JLI_MemAlloc(strlen(execname) + 20);
*oldbase++ = 0;
sprintf(newexec, "%s/%s/%s", olddir,
((wanted==64) ? LIBARCH64NAME : ".."), oldbase);
argv[0] = newexec;
}
#endif
(void)fflush(stdout);
(void)fflush(stderr);
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 *) ARCH; /* 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 "<exe_path>/libjvm.so" where <exe_path> 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 /* ifndef GAMMA */
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 the JRE universal, i.e. no arch dir? */
sprintf(libjava, "%s/jre/lib/" JAVA_DLL, path);
if (access(libjava, F_OK) == 0) {
strcat(path, "/jre");
goto found;
}
/* 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 <apphome>/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 /* ifndef GAMMA */
}
/*
* If app is "/foo/bin/javac", or "/foo/bin/sparcv9/javac" then put
* "/foo" into buf.
*/
jboolean
GetApplicationHome(char *buf, jint bufsize)
{
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
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 /* ifndef 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 = JLI_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 = JLI_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;
}
JLI_MemFree(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*)JLI_MemAlloc(PATH_MAX+1);
if (resolved != NULL) {
exec_path = realpath(dlinfo.dli_fname, resolved);
if (exec_path == NULL) {
JLI_MemFree(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 = JLI_StringDup(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<n> 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
/*
* 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_" LIBARCHNAME "_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(_ALLBSD_SOURCE)) && 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 */
" 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", "%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_" LIBARCHNAME "_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_" LIBARCHNAME "_ServerClassMachine: %s\n",
(result == JNI_TRUE ? "true" : "false"));
}
return result;
}
#endif /* __linux__ && i586 */
#if defined(_ALLBSD_SOURCE) && defined(i586)
/* The definition of a server-class machine for bsd-i586 */
jboolean
bsd_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_" LIBARCHNAME "_ServerClassMachine: %s\n",
(result == JNI_TRUE ? "true" : "false"));
}
return result;
}
#endif /* _ALLBSD_SOURCE && i586 */
/* Dispatch to the platform-specific definition of "server-class" */
jboolean
ServerClassMachine(void) {
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;
#elif 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();
#elif defined(_ALLBSD_SOURCE) && defined(i586)
result = bsd_i586_ServerClassMachine();
#else
if (_launcher_debug) {
printf("ServerClassMachine: returns default value of %s\n",
(result == JNI_TRUE ? "true" : "false"));
}
#endif
return result;
}
/*
* 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 ((JLI_AcceptableRelease(dp->d_name + offset,
info->jre_version)) && CheckSanity(dirname, dp->d_name))
if ((best == NULL) || (JLI_ExactVersionId(
dp->d_name + offset, best + best_offset) > 0)) {
if (best != NULL)
JLI_MemFree(best);
best = JLI_StringDup(dp->d_name);
best_offset = offset;
}
}
}
} while (dp != NULL);
(void) closedir(dirp);
if (best == NULL)
return (NULL);
else {
ret_str = JLI_MemAlloc(strlen(dirname) + strlen(best) + 2);
ret_str = strcat(strcat(strcpy(ret_str, dirname), "/"), best);
JLI_MemFree(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 = JLI_StringDup(system_dir);
else if ((path = getenv("JAVA_VERSION_PATH")) != NULL)
path = JLI_StringDup(path);
else
if ((home = getenv("HOME")) != NULL) {
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 = JLI_StringDup(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++;
}
JLI_MemFree(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("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 */
/*
* "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));
}
/* --- 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;
}
}
/*
* Block current thread and continue execution in a new thread
*/
int
ContinueInNewThread(int (JNICALL *continuation)(void *), jlong stack_size, void * args) {
int rslt;
#if defined(__linux__) || defined(_ALLBSD_SOURCE)
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
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)(intptr_t)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)(intptr_t)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
}
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef JAVA_MD_H
#define JAVA_MD_H
#include <limits.h>
#include <unistd.h>
#include <sys/param.h>
#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
#ifdef JAVA_ARGS
/*
* ApplicationHome is prepended to each of these entries; the resulting
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
* value of -cp option to the launcher.
*/
#ifndef APP_CLASSPATH
#define APP_CLASSPATH { "/lib/tools.jar", "/classes" }
#endif
#endif
#ifdef HAVE_GETHRTIME
/*
* Support for doing cheap, accurate interval timing.
*/
#include <sys/time.h>
#define CounterGet() (gethrtime()/1000)
#define Counter2Micros(counts) (counts)
#else
#define CounterGet() (0)
#define Counter2Micros(counts) (1)
#endif /* HAVE_GETHRTIME */
#ifdef _LP64
#define JLONG_FORMAT "%ld"
#else
#define JLONG_FORMAT "%lld"
#endif
/*
* Function prototypes.
*/
#ifndef GAMMA
char *LocateJRE(manifest_info *info);
void ExecJRE(char *jre, char **argv);
#endif
int UnsetEnv(char *name);
#endif
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include <ctype.h>
#include <windows.h>
#include <io.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <jni.h>
#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 <apphome>\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 "<exe_path>/jvm.dll" where <exe_path> 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 */
char env[MAXPATHLEN + 1];
/* gamma launcher uses ALT_JAVA_HOME environment variable or jdkpath.txt file to find JDK/JRE */
if (getenv("ALT_JAVA_HOME") != NULL) {
snprintf(buf, bufsize, "%s", getenv("ALT_JAVA_HOME"));
}
else {
char path[MAXPATHLEN + 1];
char* p;
int len;
FILE* fp;
// find the path to the currect executable
len = GetModuleFileName(NULL, path, MAXPATHLEN + 1);
if (len == 0 || len > MAXPATHLEN) {
printf("Could not get directory of current executable.");
return JNI_FALSE;
}
// remove last path component ("hotspot.exe")
p = strrchr(path, '\\');
if (p == NULL) {
printf("Could not parse directory of current executable.\n");
return JNI_FALSE;
}
*p = '\0';
// open jdkpath.txt and read JAVA_HOME from it
if (strlen(path) + strlen("\\jdkpath.txt") + 1 >= MAXPATHLEN) {
printf("Path too long: %s\n", path);
return JNI_FALSE;
}
strcat(path, "\\jdkpath.txt");
fp = fopen(path, "r");
if (fp == NULL) {
printf("Could not open file %s to get path to JDK.\n", path);
return JNI_FALSE;
}
if (fgets(buf, bufsize, fp) == NULL) {
printf("Could not read from file %s to get path to JDK.\n", path);
fclose(fp);
return JNI_FALSE;
}
// trim the buffer
p = buf + strlen(buf) - 1;
while(isspace(*p)) {
*p = '\0';
p--;
}
fclose(fp);
}
_snprintf(env, MAXPATHLEN, "JAVA_HOME=%s", buf);
_putenv(env);
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 "<top_key>/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;
}
}
/*
* 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 */
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef JAVA_MD_H
#define JAVA_MD_H
#include <jni.h>
#include <windows.h>
#include <io.h>
#ifndef GAMMA
#include "manifest_info.h"
#endif
#include "jli_util.h"
#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
* strings are concatenated (separated by PATH_SEPARATOR) and used as the
* value of -cp option to the launcher.
*/
#ifndef APP_CLASSPATH
#define APP_CLASSPATH { "\\lib\\tools.jar", "\\classes" }
#endif
#endif
/*
* Support for doing cheap, accurate interval timing.
*/
extern jlong CounterGet(void);
extern jlong Counter2Micros(jlong counts);
#ifdef JAVAW
#define main _main
extern int _main(int argc, char **argv);
#endif
#define JLONG_FORMAT "%I64d"
/*
* Function prototypes.
*/
#ifndef GAMMA
char *LocateJRE(manifest_info *info);
void ExecJRE(char *jre, char **argv);
#endif
int UnsetEnv(char *name);
#endif
...@@ -65,6 +65,7 @@ class BuildConfig { ...@@ -65,6 +65,7 @@ class BuildConfig {
String sourceBase = getFieldString(null, "SourceBase"); String sourceBase = getFieldString(null, "SourceBase");
String buildSpace = getFieldString(null, "BuildSpace"); String buildSpace = getFieldString(null, "BuildSpace");
String outDir = buildBase; String outDir = buildBase;
String jdkTargetRoot = getFieldString(null, "JdkTargetRoot");
put("Id", flavourBuild); put("Id", flavourBuild);
put("OutputDir", outDir); put("OutputDir", outDir);
...@@ -72,6 +73,7 @@ class BuildConfig { ...@@ -72,6 +73,7 @@ class BuildConfig {
put("BuildBase", buildBase); put("BuildBase", buildBase);
put("BuildSpace", buildSpace); put("BuildSpace", buildSpace);
put("OutputDll", outDir + Util.sep + outDll); put("OutputDll", outDir + Util.sep + outDll);
put("JdkTargetRoot", jdkTargetRoot);
context = new String [] {flavourBuild, flavour, build, null}; context = new String [] {flavourBuild, flavour, build, null};
} }
......
...@@ -98,11 +98,6 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 { ...@@ -98,11 +98,6 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 {
tagV(cfg.getV("LinkerFlags")); tagV(cfg.getV("LinkerFlags"));
endTag(); endTag();
startTag("PostBuildEvent");
tagData("Message", BuildConfig.getFieldString(null, "PostbuildDescription"));
tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PostbuildCommand").replace("\t", "\r\n")));
endTag();
startTag("PreLinkEvent"); startTag("PreLinkEvent");
tagData("Message", BuildConfig.getFieldString(null, "PrelinkDescription")); tagData("Message", BuildConfig.getFieldString(null, "PrelinkDescription"));
tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace("\t", "\r\n"))); tagData("Command", cfg.expandFormat(BuildConfig.getFieldString(null, "PrelinkCommand").replace("\t", "\r\n")));
...@@ -141,7 +136,9 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 { ...@@ -141,7 +136,9 @@ public class WinGammaPlatformVC10 extends WinGammaPlatformVC7 {
for (BuildConfig cfg : allConfigs) { for (BuildConfig cfg : allConfigs) {
startTag(cfg, "PropertyGroup"); startTag(cfg, "PropertyGroup");
tagData("LocalDebuggerCommand", "$(TargetDir)/hotspot.exe"); tagData("LocalDebuggerCommand", cfg.get("JdkTargetRoot") + "\\bin\\java.exe");
tagData("LocalDebuggerCommandArguments", "-XXaltjvm=$(TargetDir) -Dsun.java.launcher=gamma");
tagData("LocalDebuggerEnvironment", "JAVA_HOME=" + cfg.get("JdkTargetRoot"));
endTag(); endTag();
} }
......
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* 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
* 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 TranslateApplicationArgs
* removes "-J" prefixes. On unix platforms, the
* CreateExecutionEnvironment function from the unix java_md.c file
* processes and removes -d<n> 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<n>
* options and prevent them from being passed to the vm; this is done
* by using the machine-dependent call
* RemovableMachineDependentOption.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include <jvm.h>
#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
#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"
#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.
*/
static JavaVMOption *options;
static int numOptions, maxOptions;
/*
* Prototypes for functions internal to launcher.
*/
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, const char *jvmpath);
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);
static void SetJavaLauncherProp(void);
#ifdef JAVA_ARGS
static void TranslateApplicationArgs(int *pargc, char ***pargv);
static jboolean AddApplicationOptions(void);
#endif
static void PrintJavaVersion(JNIEnv *env);
static void PrintUsage(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 */
#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();
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)
{
char *jarfile = 0;
char *classname = 0;
char *s = 0;
char *main_class = NULL;
int ret;
InvocationFunctions ifn;
jlong start, end;
char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN];
char ** original_argv = argv;
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**)JLI_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);
printf("Using java runtime at: %s\n", jrepath);
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 */
TranslateApplicationArgs(&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, jvmpath)) {
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);
/* 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
/*
* Done with all command line processing and potential re-execs so
* 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 */
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*)JLI_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 occured */
const char * format = "Could not find the main class: %s. Program will exit.";
ReportExceptionDescription(env);
message = (char *)JLI_MemAlloc((strlen(format) +
strlen(classname)) * sizeof(char) );
messageDest = JNI_TRUE;
sprintf(message, format, classname);
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 *)JLI_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 occured */
const char * format = "Could not find the main class: %s. Program will exit.";
ReportExceptionDescription(env);
message = (char *)JLI_MemAlloc((strlen(format) +
strlen(classname)) * sizeof(char) );
messageDest = JNI_TRUE;
sprintf(message, format, classname);
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 = JLI_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 */
# 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, &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.
*/
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 = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
} else {
JavaVMOption *tmp;
maxOptions *= 2;
tmp = JLI_MemAlloc(maxOptions * sizeof(JavaVMOption));
memcpy(tmp, options, numOptions * sizeof(JavaVMOption));
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(const char *s)
{
char *def;
s = JLI_WildcardExpandClasspath(s);
def = JLI_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.
* 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)
{
char *arg;
char **new_argv;
char **new_argp;
char *operand;
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;
/*
* 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 = JLI_StringDup(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.
*
* 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 = JLI_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;
}
/*
* 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--;
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 = JLI_ParseManifest(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);
}
/*
* 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;
info.jre_version = NULL;
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.
*/
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 = 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) {
JLI_FreeManifest();
JLI_MemFree(new_argv);
return;
}
/*
* Check for correct syntax of the version specification (JSR 56).
*/
if (!JLI_ValidVersionString(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 (JLI_AcceptableRelease(FULL_VERSION, info.jre_version)) {
JLI_FreeManifest();
JLI_MemFree(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) {
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);
JLI_FreeManifest();
JLI_MemFree(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, const char *jvmpath)
{
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(jvmpath);
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 = JLI_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 = JLI_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 ||
strncmp(arg, "-splash:", 8) == 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);
JLI_MemFree(options);
return r == JNI_OK;
}
#define NULL_CHECK0(e) if ((e) == 0) return 0
#define NULL_CHECK(e) if ((e) == 0) return
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 = (*env)->FindClass(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 = (*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);
}
/*
* 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)) {
if (isEncodingSupported(env, enc) == JNI_TRUE) {
NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
"([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 = (*env)->FindClass(env, "java/lang/String"));
NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
"([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 = (*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++);
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 = JLI_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');
cls = (*env)->FindClass(env, buf);
JLI_MemFree(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 = (*env)->FindClass(env, "java/util/jar/JarFile"));
NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
"(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 command line args thus:
* javac -cp foo:foo/"*" -J-ms32m ...
* java -ms32m -cp JLI_WildcardExpandClasspath(foo:foo/"*") ...
*/
static void
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 = JLI_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] == '-') {
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;
}
/*
* For our tools, we try to add 3 VM options:
* -Denv.class.path=<envcp>
* -Dapplication.home=<apphome>
* -Djava.class.path=<appcp>
* <envcp> 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.
* <apphome> is the directory where the application is installed.
* <appcp> is the classpath to where our apps' classfiles are.
*/
static jboolean
AddApplicationOptions()
{
const int NUM_APP_CLASSPATH = (sizeof(app_classpath) / sizeof(char *));
char *envcp, *appcp, *apphome;
char home[MAXPATHLEN]; /* application home */
char separator[] = { PATH_SEPARATOR, '\0' };
int size, i;
int strlenHome;
{
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))) {
ReportErrorMessage("Can't determine application home", JNI_TRUE);
return JNI_FALSE;
}
/* 40 for '-Dapplication.home=' */
apphome = (char *)JLI_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 *)JLI_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 /* JAVA_ARGS */
/*
* 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*) JLI_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 would like to know if it's created by a standard Sun launcher, or by
* user native application, the following property indicates the former.
*/
void SetJavaLauncherProp() {
AddOption("-Dsun.java.launcher=" LAUNCHER_TYPE, NULL);
}
/*
* Prints the version information from the java.version and other properties.
*/
static void
PrintJavaVersion(JNIEnv *env)
{
jclass ver;
jmethodID print;
NULL_CHECK(ver = (*env)->FindClass(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)
{
#ifndef GAMMA
int i;
#endif
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<knownVMsCount; i++) {
if (knownVMs[i].flag == VM_KNOWN)
fprintf(stdout, " %s\t to select the \"%s\" VM\n",
knownVMs[i].name, knownVMs[i].name+1);
}
for (i=1; i<knownVMsCount; i++) {
if (knownVMs[i].flag == VM_ALIASED_TO)
fprintf(stdout, " %s\t is a synonym for "
"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;
const char* punctuation = ".";
const char* reason = "";
if ((knownVMs[0].flag == VM_IF_SERVER_CLASS) &&
(ServerClassMachine() == JNI_TRUE)) {
defaultVM = knownVMs[0].server_class+1;
punctuation = ", ";
reason = "because you are running on a server-class machine.\n";
}
fprintf(stdout, " The default VM is %s%s\n",
defaultVM, punctuation);
fprintf(stdout, " %s\n",
reason);
}
#endif /* ifndef GAMMA */
fprintf(stdout,
" -cp <class search path of directories and zip/jar files>\n"
" -classpath <class search path of directories and zip/jar files>\n"
" A %c separated list of directories, JAR archives,\n"
" and ZIP archives to search for class files.\n"
" -D<name>=<value>\n"
" set a system property\n"
" -verbose[:class|gc|jni]\n"
" enable verbose output\n"
" -version print product version and exit\n"
" -version:<value>\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[:<packagename>...|:<classname>]\n"
" -enableassertions[:<packagename>...|:<classname>]\n"
" enable assertions\n"
" -da[:<packagename>...|:<classname>]\n"
" -disableassertions[:<packagename>...|:<classname>]\n"
" disable assertions\n"
" -esa | -enablesystemassertions\n"
" enable system assertions\n"
" -dsa | -disablesystemassertions\n"
" disable system assertions\n"
" -agentlib:<libname>[=<options>]\n"
" load native agent library <libname>, e.g. -agentlib:hprof\n"
" see also, -agentlib:jdwp=help and -agentlib:hprof=help\n"
" -agentpath:<pathname>[=<options>]\n"
" load native agent library by full pathname\n"
" -javaagent:<jarpath>[=<options>]\n"
" load Java programming language agent, see java.lang.instrument\n"
" -splash:<imagepath>\n"
" show splash screen with specified image\n"
,PATH_SEPARATOR);
}
/*
* Print usage message for -X options.
*/
static jint
PrintXUsage(const char *jvmpath)
{
/*
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";
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);
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 = NULL;
char *serverClassVMName = NULL;
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 JLI_StringDup 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 = JLI_StringDup(line);
knownVMs[cnt].flag = vmType;
switch (vmType) {
default:
break;
case VM_ALIASED_TO:
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 = 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);
}
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*) JLI_MemAlloc(newMax * sizeof(struct vmdesc));
if (knownVMs != NULL) {
memcpy(newKnownVMs, knownVMs, knownVMsLimit * sizeof(struct vmdesc));
}
JLI_MemFree(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++) {
JLI_MemFree(knownVMs[i].name);
knownVMs[i].name = NULL;
}
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 */
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef _JAVA_H_
#define _JAVA_H_
/*
* Get system specific defines.
*/
#include "jni.h"
#include "java_md.h"
#include "jli_util.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();
/*
* 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 AddOption(char *str, void *info);
/*
* Make launcher spit debug output.
*/
extern jboolean _launcher_debug;
#endif /* _JAVA_H_ */
/*
* 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 <stdio.h>
#include <string.h>
#include "jli_util.h"
#ifdef GAMMA
#ifdef TARGET_OS_FAMILY_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);
}
/*
* 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 <stdlib.h>
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 */
/*
* 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 <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
#include "jli_util.h"
#ifdef _WIN32
#include <windows.h>
#else /* Unix */
#include <unistd.h>
#include <dirent.h>
#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) {
FileList_free(fl);
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;
*/
/*
* 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 */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册