This commit is contained in:
Lana Steuck 2015-11-12 14:15:05 -08:00
commit d900f2f444
332 changed files with 11687 additions and 2286 deletions

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -45,8 +45,16 @@ endif
# #
# Import hotspot # Import hotspot
# #
# Don't import jsig library for static builds
ifneq ($(STATIC_BUILD), true)
JSIG_IMPORT = jsig.*
else
JSIG_IMPORT =
endif
HOTSPOT_BASE_IMPORT_FILES := \ HOTSPOT_BASE_IMPORT_FILES := \
$(addprefix $(LIBRARY_PREFIX), jvm.* jsig.* jvm_db.* jvm_dtrace.*) \ $(addprefix $(LIBRARY_PREFIX), jvm.* $(JSIG_IMPORT) jvm_db.* jvm_dtrace.*) \
Xusage.txt \ Xusage.txt \
# #
@ -79,6 +87,7 @@ SA_TARGETS := $(COPY_HOTSPOT_SA)
################################################################################ ################################################################################
ifneq ($(STATIC_BUILD), true)
ifeq ($(OPENJDK_TARGET_OS), macosx) ifeq ($(OPENJDK_TARGET_OS), macosx)
JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \ JSIG_DEBUGINFO := $(strip $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig$(SHARED_LIBRARY_SUFFIX).dSYM) \
$(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) ) $(wildcard $(HOTSPOT_DIST)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/libjsig.diz) )
@ -109,6 +118,7 @@ ifneq ($(OPENJDK_TARGET_OS), windows)
endif endif
endif endif
endif endif
endif
$(BASE_INSTALL_LIBRARIES_HERE)/server/%$(SHARED_LIBRARY_SUFFIX): $(BASE_INSTALL_LIBRARIES_HERE)/%$(SHARED_LIBRARY_SUFFIX) $(BASE_INSTALL_LIBRARIES_HERE)/server/%$(SHARED_LIBRARY_SUFFIX): $(BASE_INSTALL_LIBRARIES_HERE)/%$(SHARED_LIBRARY_SUFFIX)
$(MKDIR) -p $(@D) $(MKDIR) -p $(@D)

View File

@ -50,12 +50,12 @@ public class $NAME_CLZ$ extends Charset
public CharsetDecoder newDecoder() { public CharsetDecoder newDecoder() {
initb2c(); initb2c();
return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$); return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$);
} }
public CharsetEncoder newEncoder() { public CharsetEncoder newEncoder() {
initc2b(); initc2b();
return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex); return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$);
} }
$B2C$ $B2C$

View File

@ -48,11 +48,11 @@ public class $NAME_CLZ$ extends Charset implements HistoricallyNamedCharset
} }
public CharsetDecoder newDecoder() { public CharsetDecoder newDecoder() {
return new SingleByte.Decoder(this, b2c); return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$);
} }
public CharsetEncoder newEncoder() { public CharsetEncoder newEncoder() {
return new SingleByte.Encoder(this, c2b, c2bIndex); return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$);
} }
private final static String b2cTable = $B2CTABLE$ private final static String b2cTable = $B2CTABLE$

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -39,14 +39,14 @@ include GensrcExceptions.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \ $(eval $(call SetupCompileProperties, LIST_RESOURCE_BUNDLE, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources)), \ CLASS := ListResourceBundle, \
ListResourceBundle)) ))
$(eval $(call SetupCompileProperties, SUN_UTIL, \ $(eval $(call SetupCompileProperties, SUN_UTIL, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources)), \ CLASS := sun.util.resources.LocaleNamesBundle, \
sun.util.resources.LocaleNamesBundle)) ))
GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL) GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -66,11 +66,11 @@ else
PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources
endif endif
PROP_SRC_FILES := $(filter-out %cursors.properties, \
$(filter %.properties, $(call CacheFind, $(PROP_SRC_DIRS))))
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(PROP_SRC_FILES), ListResourceBundle)) SRC_DIRS := $(PROP_SRC_DIRS), \
EXCLUDE := %cursors.properties, \
CLASS := ListResourceBundle, \
))
GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES) GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -30,9 +30,9 @@ include GensrcCommon.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)), \ CLASS := ListResourceBundle, \
ListResourceBundle)) ))
TARGETS += $(COMPILE_PROPERTIES) TARGETS += $(COMPILE_PROPERTIES)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -33,9 +33,9 @@ $(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-java.management.gmk))
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources)), \ CLASS := ListResourceBundle, \
ListResourceBundle)) ))
TARGETS += $(COMPILE_PROPERTIES) TARGETS += $(COMPILE_PROPERTIES)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -30,10 +30,9 @@ include GensrcCommon.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources, \
$(call CacheFind, \ CLASS := ListResourceBundle, \
$(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/tools/jimage/resources)), \ ))
ListResourceBundle))
TARGETS += $(COMPILE_PROPERTIES) TARGETS += $(COMPILE_PROPERTIES)

View File

@ -30,10 +30,9 @@ include GensrcCommon.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources, \
$(call CacheFind, \ CLASS := ListResourceBundle, \
$(JDK_TOPDIR)/src/jdk.jartool/share/classes/sun/tools/jar/resources)), \ ))
ListResourceBundle))
TARGETS += $(COMPILE_PROPERTIES) TARGETS += $(COMPILE_PROPERTIES)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -91,9 +91,9 @@ endif
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources)), \ CLASS := ListResourceBundle, \
ListResourceBundle)) ))
GENSRC_JDK_JDI += $(COMPILE_PROPERTIES) GENSRC_JDK_JDI += $(COMPILE_PROPERTIES)

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -36,9 +36,9 @@ include GensrcCLDR.gmk
include GensrcProperties.gmk include GensrcProperties.gmk
$(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \ $(eval $(call SetupCompileProperties, COMPILE_PROPERTIES, \
$(filter %.properties, \ SRC_DIRS := $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources, \
$(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \ CLASS := sun.util.resources.LocaleNamesBundle, \
sun.util.resources.LocaleNamesBundle)) ))
# Skip generating zh_HK from zh_TW for this module. # Skip generating zh_HK from zh_TW for this module.
GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES)) GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES))

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -49,20 +49,30 @@ define SetupCopy-zh_HK
endef endef
################################################################################ ################################################################################
# Creates a rule that runs CompileProperties on a set of properties files. # Setup make rules that runs CompileProperties on a set of properties files.
# Param 1 - Variable to add targets to, must not contain space #
# Param 2 - Properties files to process # Parameter 1 is the name of the rule. This name is used as variable prefix,
# Param 3 - The super class for the generated classes # and the targets generated are listed in a variable by that name.
# Param 4 - Module path root, defaults to $(JDK_TOPDIR)/src #
define SetupCompileProperties # Remaining parameters are named arguments. These include:
$1_SRCS := $2 # SRC_DIRS Directories containing properties files to process.
$1_CLASS := $3 # EXCLUDE Exclude files matching this pattern.
$1_MODULE_PATH_ROOT := $4 # CLASS The super class for the generated classes.
# MODULE_PATH_ROOT Module path root, defaults to $(JDK_TOPDIR)/src.
SetupCompileProperties = $(NamedParamsMacroTemplate)
define SetupCompilePropertiesBody
# Set default value unless overridden
ifeq ($$($1_MODULE_PATH_ROOT), ) ifeq ($$($1_MODULE_PATH_ROOT), )
$1_MODULE_PATH_ROOT := $(JDK_TOPDIR)/src $1_MODULE_PATH_ROOT := $(JDK_TOPDIR)/src
endif endif
# Locate all properties files in the given source dirs.
$1_SRC_FILES := $$(filter %.properties, $$(call CacheFind, $$($1_SRC_DIRS)))
ifneq ($$($1_EXCLUDE), )
$1_SRC_FILES := $$(filter-out $$($1_EXCLUDE), $$($1_SRC_FILES))
endif
# Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties # Convert .../src/<module>/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties
# to .../support/gensrc/<module>/com/sun/tools/javac/resources/javac_zh_CN.java # to .../support/gensrc/<module>/com/sun/tools/javac/resources/javac_zh_CN.java
# Strip away prefix and suffix, leaving for example only: # Strip away prefix and suffix, leaving for example only:
@ -72,7 +82,7 @@ define SetupCompileProperties
$$(patsubst %.properties, %.java, \ $$(patsubst %.properties, %.java, \
$$(subst /$(OPENJDK_TARGET_OS)/classes,, \ $$(subst /$(OPENJDK_TARGET_OS)/classes,, \
$$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \ $$(subst /$(OPENJDK_TARGET_OS_TYPE)/classes,, \
$$(subst /share/classes,, $$($1_SRCS)))))) $$(subst /share/classes,, $$($1_SRC_FILES))))))
# Generate the package dirs for the to be generated java files. Sort to remove # Generate the package dirs for the to be generated java files. Sort to remove
# duplicates. # duplicates.
@ -82,22 +92,22 @@ define SetupCompileProperties
# "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle" # "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle"
# suitable to be fed into the CompileProperties command. # suitable to be fed into the CompileProperties command.
$1_CMDLINE := $$(subst _SPACE_, $(SPACE), \ $1_CMDLINE := $$(subst _SPACE_, $(SPACE), \
$$(join $$(addprefix -compile_SPACE_, $$($1_SRCS)), \ $$(join $$(addprefix -compile_SPACE_, $$($1_SRC_FILES)), \
$$(addsuffix _SPACE_$$($1_CLASS), \ $$(addsuffix _SPACE_$$($1_CLASS), \
$$(addprefix _SPACE_, $$($1_JAVAS))))) $$(addprefix _SPACE_, $$($1_JAVAS)))))
$1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.done $1_TARGET := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.marker
$1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline $1_CMDLINE_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline
# Now setup the rule for the generation of the resource bundles. # Now setup the rule for the generation of the resource bundles.
$$($1_TARGET): $$($1_SRCS) $$($1_JAVAS) $(BUILD_TOOLS_JDK) $$($1_TARGET): $$($1_SRC_FILES) $$($1_JAVAS) $(BUILD_TOOLS_JDK)
$(MKDIR) -p $$(@D) $$($1_DIRS) $(MKDIR) -p $$(@D) $$($1_DIRS)
$(ECHO) Compiling $$(words $$($1_SRCS)) properties into resource bundles for $(MODULE) $(ECHO) Compiling $$(words $$($1_SRC_FILES)) properties into resource bundles for $(MODULE)
$$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE))) $$(eval $$(call ListPathsSafely, $1_CMDLINE, $$($1_CMDLINE_FILE)))
$(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE) $(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE)
$(TOUCH) $$@ $(TOUCH) $$@
$$($1_JAVAS): $$($1_SRCS) $$($1_JAVAS): $$($1_SRC_FILES)
# Create zh_HK versions of all zh_TW files created above # Create zh_HK versions of all zh_TW files created above
$$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS)))) $$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS))))

View File

@ -122,8 +122,23 @@ define SetupBuildLauncherBody
endif endif
$1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"' $1_CFLAGS += -DPACKAGE_PATH='"$(PACKAGE_PATH)"'
$1_LDFLAGS += -Wl,-all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a \ $1_LDFLAGS += -Wl,-all_load \
-sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE) -sectcreate __TEXT __info_plist $(MACOSX_PLIST_DIR)/$$($1_PLIST_FILE)
ifeq ($(STATIC_BUILD), true)
$1_LDFLAGS += -exported_symbols_list \
$(SUPPORT_OUTPUTDIR)/build-static/exported.symbols
$1_LIBS += \
$(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs/java.base -name "*.a") \
$(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libdt_socket.a \
$(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/libjdwp.a \
$(SUPPORT_OUTPUTDIR)/native/java.base/$(LIBRARY_PREFIX)fdlibm$(STATIC_LIBRARY_SUFFIX) \
-framework CoreFoundation \
-framework Foundation \
-framework SystemConfiguration \
-lstdc++ -liconv
else
$1_LIBS += $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a
endif
$1_LIBS += -framework Cocoa -framework Security \ $1_LIBS += -framework Cocoa -framework Security \
-framework ApplicationServices -framework ApplicationServices
endif endif

View File

@ -476,7 +476,7 @@ endif
ifeq ($(USE_EXTERNAL_LIBJPEG), true) ifeq ($(USE_EXTERNAL_LIBJPEG), true)
LIBJPEG_LIBS := -ljpeg LIBJPEG_LIBS := -ljpeg
BUILD_LIBJAVAJPEG_INCLUDE_FILES := \ BUILD_LIBJAVAJPEG_INCLUDE_FILES := \
imageIOJPEG.c \ imageioJPEG.c \
jpegdecoder.c jpegdecoder.c
BUILD_LIBJAVAJPEG_HEADERS := BUILD_LIBJAVAJPEG_HEADERS :=
else else

View File

@ -435,10 +435,14 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES))) DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
ifeq ($(STATIC_BUILD), true)
TARGETS += $(BUILD_LIBJLI_STATIC)
else
$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC) $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a: $(BUILD_LIBJLI_STATIC)
$(call install-file) $(call install-file)
TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a TARGETS += $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static.a
endif
else ifeq ($(OPENJDK_TARGET_OS), aix) else ifeq ($(OPENJDK_TARGET_OS), aix)
# AIX also requires a static libjli because the compiler doesn't support '-rpath' # AIX also requires a static libjli because the compiler doesn't support '-rpath'

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -33,3 +33,29 @@ include CoreLibraries.gmk
include NetworkingLibraries.gmk include NetworkingLibraries.gmk
include NioLibraries.gmk include NioLibraries.gmk
include SecurityLibraries.gmk include SecurityLibraries.gmk
ifeq ($(STATIC_BUILD), true)
JAVA_BASE_EXPORT_SYMBOLS_SRC := \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli/$(LIBRARY_PREFIX)jli.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)java.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)net.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)nio.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)verify.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)zip.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/$(LIBRARY_PREFIX)jimage.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/server/$(LIBRARY_PREFIX)jvm.symbols \
#
JAVA_BASE_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/java.base.symbols
$(JAVA_BASE_EXPORT_SYMBOL_FILE): $(JAVA_BASE_EXPORT_SYMBOLS_SRC)
$(ECHO) $(LOG_INFO) "Generating java.base.symbols file"
$(CAT) $^ > $@
# The individual symbol files is generated when the respective lib is built
$(JAVA_BASE_EXPORT_SYMBOLS_SRC): $(BUILD_LIBJLI) $(BUILD_LIBJAVA) \
$(BUILD_LIBNET) $(BUILD_LIBNIO) $(BUILD_LIBVERIFY) $(BUILD_LIBZIP) \
$(BUILD_LIBJIMAGE)
TARGETS += $(JAVA_BASE_EXPORT_SYMBOL_FILE)
endif

View File

@ -102,3 +102,23 @@ $(BUILD_LIBJDWP): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIBJDWP) TARGETS += $(BUILD_LIBJDWP)
################################################################################ ################################################################################
ifeq ($(STATIC_BUILD), true)
JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC := \
$(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)dt_socket.symbols \
$(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/$(LIBRARY_PREFIX)jdwp.symbols
JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE := $(SUPPORT_OUTPUTDIR)/modules_libs/jdk.jdwp.agent/jdk.jdwp.agent.symbols
$(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE): $(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC)
$(ECHO) $(LOG_INFO) "Generating jdk.jdwp.agent symbols file"
$(CAT) $^ > $@
# The individual symbol files is generated when the respective lib is built
$(JDK_JDWP_AGENT_EXPORT_SYMBOLS_SRC): $(BUILD_LIBDT_SOCKET) $(BUILD_LIBJDWP)
TARGETS += $(JDK_JDWP_AGENT_EXPORT_SYMBOL_FILE)
endif
################################################################################

View File

@ -26,6 +26,8 @@
include LibCommon.gmk include LibCommon.gmk
ifeq ($(OPENJDK_TARGET_OS), macosx) ifeq ($(OPENJDK_TARGET_OS), macosx)
# JavaNativeFoundation framework not supported in static builds
ifneq ($(STATIC_BUILD), true)
################################################################################ ################################################################################
@ -61,3 +63,4 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
################################################################################ ################################################################################
endif endif
endif

View File

@ -211,6 +211,7 @@ SUNWprivate_1.1 {
Java_java_lang_SecurityManager_getClassContext; Java_java_lang_SecurityManager_getClassContext;
Java_java_lang_Shutdown_halt0; Java_java_lang_Shutdown_halt0;
Java_java_lang_String_intern; Java_java_lang_String_intern;
Java_java_lang_StringUTF16_isBigEndian;
Java_java_lang_System_identityHashCode; Java_java_lang_System_identityHashCode;
Java_java_lang_System_initProperties; Java_java_lang_System_initProperties;
Java_java_lang_System_mapLibraryName; Java_java_lang_System_mapLibraryName;

View File

@ -57,6 +57,7 @@ text: .text%Java_java_io_UnixFileSystem_list;
text: .text%JNU_ClassString; text: .text%JNU_ClassString;
text: .text%JNU_CopyObjectArray; text: .text%JNU_CopyObjectArray;
text: .text%Java_java_lang_String_intern; text: .text%Java_java_lang_String_intern;
text: .text%Java_java_lang_StringUTF16_isBigEndian;
text: .text%Java_java_lang_ClassLoader_findLoadedClass0; text: .text%Java_java_lang_ClassLoader_findLoadedClass0;
text: .text%Java_java_lang_ClassLoader_findBootstrapClass; text: .text%Java_java_lang_ClassLoader_findBootstrapClass;
text: .text%Java_java_lang_Throwable_fillInStackTrace; text: .text%Java_java_lang_Throwable_fillInStackTrace;

View File

@ -29,6 +29,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__;
text: .text%Java_sun_reflect_Reflection_getCallerClass__I; text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
text: .text%Java_java_lang_Class_forName0; text: .text%Java_java_lang_Class_forName0;
text: .text%Java_java_lang_String_intern; text: .text%Java_java_lang_String_intern;
text: .text%Java_java_lang_StringUTF16_isBigEndian;
text: .text%Java_java_lang_Float_floatToRawIntBits; text: .text%Java_java_lang_Float_floatToRawIntBits;
text: .text%Java_java_lang_Double_doubleToRawLongBits; text: .text%Java_java_lang_Double_doubleToRawLongBits;
text: .text%Java_java_lang_ClassLoader_findLoadedClass0; text: .text%Java_java_lang_ClassLoader_findLoadedClass0;

View File

@ -31,6 +31,7 @@ text: .text%Java_sun_reflect_Reflection_getCallerClass__;
text: .text%Java_sun_reflect_Reflection_getCallerClass__I; text: .text%Java_sun_reflect_Reflection_getCallerClass__I;
text: .text%Java_java_lang_Class_forName0; text: .text%Java_java_lang_Class_forName0;
text: .text%Java_java_lang_String_intern; text: .text%Java_java_lang_String_intern;
text: .text%Java_java_lang_StringUTF16_isBigEndian;
text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0; text: .text%Java_sun_reflect_NativeConstructorAccessorImpl_newInstance0;
text: .text%Java_java_lang_Throwable_fillInStackTrace; text: .text%Java_java_lang_Throwable_fillInStackTrace;
text: .text%Java_java_lang_System_setOut0; text: .text%Java_java_lang_System_setOut0;

View File

@ -75,6 +75,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_makePipe; Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes; Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal; Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_iovMax;
Java_sun_nio_ch_KQueue_kqueue; Java_sun_nio_ch_KQueue_kqueue;
Java_sun_nio_ch_KQueue_keventRegister; Java_sun_nio_ch_KQueue_keventRegister;
Java_sun_nio_ch_KQueue_keventPoll; Java_sun_nio_ch_KQueue_keventPoll;

View File

@ -197,6 +197,7 @@ public class DBCS {
.replace("$B1MAX$" , "0x" + Integer.toString(b1Max, 16)) .replace("$B1MAX$" , "0x" + Integer.toString(b1Max, 16))
.replace("$B2MIN$" , "0x" + Integer.toString(b2Min, 16)) .replace("$B2MIN$" , "0x" + Integer.toString(b2Min, 16))
.replace("$B2MAX$" , "0x" + Integer.toString(b2Max, 16)) .replace("$B2MAX$" , "0x" + Integer.toString(b2Max, 16))
.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false")
.replace("$B2C$", b2c) .replace("$B2C$", b2c)
.replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16)) .replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16))
.replace("$NONROUNDTRIP_B2C$", b2cNR) .replace("$NONROUNDTRIP_B2C$", b2cNR)

View File

@ -175,6 +175,9 @@ public class SBCS {
else else
line = " return (cs instanceof " + clzName + ");"; line = " return (cs instanceof " + clzName + ");";
} }
if (line.indexOf("$ASCIICOMPATIBLE$") != -1) {
line = line.replace("$ASCIICOMPATIBLE$", isASCII ? "true" : "false");
}
if (line.indexOf("$B2CTABLE$") != -1) { if (line.indexOf("$B2CTABLE$") != -1) {
line = line.replace("$B2CTABLE$", b2c); line = line.replace("$B2CTABLE$", b2c);
} }

View File

@ -841,7 +841,7 @@ public class WrapperGenerator {
pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" ); pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
pw.println("package "+package_name+";\n"); pw.println("package "+package_name+";\n");
pw.println("import sun.misc.*;\n"); pw.println("import jdk.internal.misc.Unsafe;\n");
pw.println("import sun.util.logging.PlatformLogger;"); pw.println("import sun.util.logging.PlatformLogger;");
String baseClass = stp.getBaseClass(); String baseClass = stp.getBaseClass();
if (baseClass == null) { if (baseClass == null) {
@ -941,7 +941,7 @@ public class WrapperGenerator {
pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" ); pw.println("// This file is an automatically generated file, please do not edit this file, modify the WrapperGenerator.java file instead !\n" );
pw.println("package "+package_name+";\n"); pw.println("package "+package_name+";\n");
pw.println("import sun.misc.Unsafe;\n"); pw.println("import jdk.internal.misc.Unsafe;\n");
pw.println("class " + ft.getName() + " {"); pw.println("class " + ft.getName() + " {");
pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;"); pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;");
pw.println("\tprivate boolean __executed = false;"); pw.println("\tprivate boolean __executed = false;");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -65,6 +65,51 @@ void deallocate(jvmtiEnv *jvmti, void *ptr);
void *allocate(jvmtiEnv *jvmti, jint len); void *allocate(jvmtiEnv *jvmti, jint len);
void add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name); void add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name);
#ifdef STATIC_BUILD
/* Macros for handling declaration of static/dynamic
* Agent library Load/Attach/Unload functions
*
* DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
* generate the appropriate entrypoint names based on static
* versus dynamic builds.
*
* STATIC_BUILD must be defined to build static versions of these libraries.
* LIBRARY_NAME must be set to the name of the library for static builds.
*/
#define ADD_LIB_NAME3(name, lib) name ## lib
#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
#define DEF_Agent_OnLoad \
ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
{ \
jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
} \
jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
#define DEF_Agent_OnAttach \
ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
{ \
jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
} \
jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
#define DEF_Agent_OnUnload \
ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
{ \
void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
} \
void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
#else
#define DEF_Agent_OnLoad Agent_OnLoad
#define DEF_Agent_OnAttach Agent_OnAttach
#define DEF_Agent_OnUnload Agent_OnUnload
#endif
#ifdef __cplusplus #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -225,7 +225,7 @@ compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size,
* event here. * event here.
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
jint rc; jint rc;
jvmtiError err; jvmtiError err;
@ -272,6 +272,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
/* Agent_OnUnload() is called last */ /* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -148,7 +148,7 @@ gc_finish(jvmtiEnv* jvmti_env)
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
jint rc; jint rc;
jvmtiError err; jvmtiError err;
@ -193,6 +193,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
/* Agent_OnUnload() is called last */ /* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -894,7 +894,7 @@ parse_agent_options(char *options)
* loaded. This is the first code executed. * loaded. This is the first code executed.
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
static GlobalAgentData data; static GlobalAgentData data;
jvmtiEnv *jvmti; jvmtiEnv *jvmti;
@ -1010,7 +1010,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
* unloaded. This is the last code executed. * unloaded. This is the last code executed.
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
/* Skip any cleanup, VM is about to die anyway */ /* Skip any cleanup, VM is about to die anyway */
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -64,9 +64,4 @@
#include "agent_util.h" #include "agent_util.h"
/* Agent library externals to export. */
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -235,7 +235,7 @@ vmDeath(jvmtiEnv *jvmti, JNIEnv *env)
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
jint rc; jint rc;
jvmtiError err; jvmtiError err;
@ -283,6 +283,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
/* Agent_OnUnload() is called last */ /* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -373,7 +373,7 @@ parse_agent_options(char *options)
* loaded. This is the first code executed. * loaded. This is the first code executed.
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
static GlobalAgentData data; static GlobalAgentData data;
jvmtiEnv *jvmti; jvmtiEnv *jvmti;
@ -467,7 +467,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
* unloaded. This is the last code executed. * unloaded. This is the last code executed.
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
/* Make sure all malloc/calloc/strdup space is freed */ /* Make sure all malloc/calloc/strdup space is freed */
if ( gdata->include != NULL ) { if ( gdata->include != NULL ) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -64,9 +64,4 @@
#include "agent_util.h" #include "agent_util.h"
/* Agent library externals to export. */
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -697,7 +697,7 @@ parse_agent_options(char *options)
* loaded. This is the first code executed. * loaded. This is the first code executed.
*/ */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
static GlobalAgentData data; static GlobalAgentData data;
jvmtiEnv *jvmti; jvmtiEnv *jvmti;
@ -795,7 +795,7 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
* unloaded. This is the last code executed. * unloaded. This is the last code executed.
*/ */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
/* Make sure all malloc/calloc/strdup space is freed */ /* Make sure all malloc/calloc/strdup space is freed */
if ( gdata->include != NULL ) { if ( gdata->include != NULL ) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -64,9 +64,4 @@
#include "agent_util.h" #include "agent_util.h"
/* Agent library externals to export. */
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm);
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -89,7 +89,7 @@ vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
jint rc; jint rc;
jvmtiError err; jvmtiError err;
@ -116,6 +116,6 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
/* Agent_OnUnload() is called last */ /* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -37,6 +37,10 @@
* this sample code. * this sample code.
*/ */
#ifdef STATIC_BUILD
#define Monitor WaiterMonitor
#endif
/* C++ Monitor class */ /* C++ Monitor class */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -37,6 +37,9 @@
* this sample code. * this sample code.
*/ */
#ifdef STATIC_BUILD
#define Thread WaiterThread
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -243,7 +243,7 @@ extern "C" {
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */ /* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{ {
jvmtiEnv *jvmti; jvmtiEnv *jvmti;
jint rc; jint rc;
@ -288,7 +288,7 @@ extern "C" {
/* Agent_OnUnload() is called last */ /* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm) DEF_Agent_OnUnload(JavaVM *vm)
{ {
} }

View File

@ -34,7 +34,7 @@ import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
* AsynchronousChannelGroup implementation based on the AIX pollset framework. * AsynchronousChannelGroup implementation based on the AIX pollset framework.

View File

@ -26,7 +26,7 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.IOException; import java.io.IOException;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
* Provides access to the Linux epoll facility. * Provides access to the Linux epoll facility.

View File

@ -29,7 +29,7 @@ import java.nio.file.attribute.*;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.io.IOException; import java.io.IOException;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixNativeDispatcher.*;
import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixConstants.*;

View File

@ -29,7 +29,7 @@ import java.nio.file.*;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixConstants.*;
import static sun.nio.fs.LinuxNativeDispatcher.*; import static sun.nio.fs.LinuxNativeDispatcher.*;

View File

@ -30,7 +30,7 @@ import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import static sun.nio.fs.UnixNativeDispatcher.*; import static sun.nio.fs.UnixNativeDispatcher.*;
import static sun.nio.fs.UnixConstants.*; import static sun.nio.fs.UnixConstants.*;

View File

@ -26,7 +26,7 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.IOException; import java.io.IOException;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
* Provides access to the BSD kqueue facility. * Provides access to the BSD kqueue facility.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -35,13 +35,15 @@
#include "java_props_macosx.h" #include "java_props_macosx.h"
// need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded // need dlopen/dlsym trick to avoid pulling in JavaRuntimeSupport before libjava.dylib is loaded
static void *getJRSFramework() { static void *getJRSFramework() {
static void *jrsFwk = NULL; static void *jrsFwk = NULL;
#ifndef STATIC_BUILD
// JavaRuntimeSupport doesn't support static Java runtimes
if (jrsFwk == NULL) { if (jrsFwk == NULL) {
jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL); jrsFwk = dlopen("/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaRuntimeSupport.framework/JavaRuntimeSupport", RTLD_LAZY | RTLD_LOCAL);
} }
#endif
return jrsFwk; return jrsFwk;
} }

View File

@ -245,6 +245,8 @@ static InvocationFunctions *GetExportedJNIFunctions() {
return sExportedJNIFunctions = fxns; return sExportedJNIFunctions = fxns;
} }
#ifndef STATIC_BUILD
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
JNI_GetDefaultJavaVMInitArgs(void *args) { JNI_GetDefaultJavaVMInitArgs(void *args) {
InvocationFunctions *ifn = GetExportedJNIFunctions(); InvocationFunctions *ifn = GetExportedJNIFunctions();
@ -265,6 +267,7 @@ JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs) {
if (ifn == NULL) return JNI_ERR; if (ifn == NULL) return JNI_ERR;
return ifn->GetCreatedJavaVMs(vmBuf, bufLen, nVMs); return ifn->GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
} }
#endif
/* /*
* Allow JLI-aware launchers to specify a client/server preference * Allow JLI-aware launchers to specify a client/server preference
@ -303,7 +306,12 @@ static void *apple_main (void *arg)
objc_registerThreadWithCollector(); objc_registerThreadWithCollector();
if (main_fptr == NULL) { if (main_fptr == NULL) {
#ifdef STATIC_BUILD
extern int main(int argc, char **argv);
main_fptr = &main;
#else
main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); main_fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
#endif
if (main_fptr == NULL) { if (main_fptr == NULL) {
JLI_ReportErrorMessageSys("error locating main entrypoint\n"); JLI_ReportErrorMessageSys("error locating main entrypoint\n");
exit(1); exit(1);
@ -588,6 +596,9 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
JLI_TraceLauncher("Does `%s' exist ... ", jvmpath); JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
#ifdef STATIC_BUILD
return JNI_TRUE;
#else
if (stat(jvmpath, &s) == 0) { if (stat(jvmpath, &s) == 0) {
JLI_TraceLauncher("yes.\n"); JLI_TraceLauncher("yes.\n");
return JNI_TRUE; return JNI_TRUE;
@ -595,6 +606,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
JLI_TraceLauncher("no.\n"); JLI_TraceLauncher("no.\n");
return JNI_FALSE; return JNI_FALSE;
} }
#endif
} }
/* /*
@ -607,10 +619,18 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
if (GetApplicationHome(path, pathsize)) { if (GetApplicationHome(path, pathsize)) {
/* Is JRE co-located with the application? */ /* Is JRE co-located with the application? */
#ifdef STATIC_BUILD
char jvm_cfg[MAXPATHLEN];
JLI_Snprintf(jvm_cfg, sizeof(jvm_cfg), "%s/lib/jvm.cfg", path);
if (access(jvm_cfg, F_OK) == 0) {
return JNI_TRUE;
}
#else
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path); JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
if (access(libjava, F_OK) == 0) { if (access(libjava, F_OK) == 0) {
return JNI_TRUE; return JNI_TRUE;
} }
#endif
/* ensure storage for path + /jre + NULL */ /* ensure storage for path + /jre + NULL */
if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) { if ((JLI_StrLen(path) + 4 + 1) > (size_t) pathsize) {
JLI_TraceLauncher("Insufficient space to store JRE path\n"); JLI_TraceLauncher("Insufficient space to store JRE path\n");
@ -629,6 +649,24 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
Dl_info selfInfo; Dl_info selfInfo;
dladdr(&GetJREPath, &selfInfo); dladdr(&GetJREPath, &selfInfo);
#ifdef STATIC_BUILD
char jvm_cfg[MAXPATHLEN];
char *p = NULL;
strncpy(jvm_cfg, selfInfo.dli_fname, MAXPATHLEN);
p = strrchr(jvm_cfg, '/'); *p = '\0';
p = strrchr(jvm_cfg, '/');
if (strcmp(p, "/.") == 0) {
*p = '\0';
p = strrchr(jvm_cfg, '/'); *p = '\0';
}
else *p = '\0';
strncpy(path, jvm_cfg, pathsize);
strncat(jvm_cfg, "/lib/jvm.cfg", MAXPATHLEN);
if (access(jvm_cfg, F_OK) == 0) {
return JNI_TRUE;
}
#endif
char *realPathToSelf = realpath(selfInfo.dli_fname, path); char *realPathToSelf = realpath(selfInfo.dli_fname, path);
if (realPathToSelf != path) { if (realPathToSelf != path) {
return JNI_FALSE; return JNI_FALSE;
@ -664,7 +702,11 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn)
JLI_TraceLauncher("JVM path is %s\n", jvmpath); JLI_TraceLauncher("JVM path is %s\n", jvmpath);
#ifndef STATIC_BUILD
libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL); libjvm = dlopen(jvmpath, RTLD_NOW + RTLD_GLOBAL);
#else
libjvm = dlopen(NULL, RTLD_FIRST);
#endif
if (libjvm == NULL) { if (libjvm == NULL) {
JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); JLI_ReportErrorMessage(DLL_ERROR1, __LINE__);
JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror());
@ -714,9 +756,14 @@ SetExecname(char **argv)
char* exec_path = NULL; char* exec_path = NULL;
{ {
Dl_info dlinfo; Dl_info dlinfo;
int (*fptr)();
#ifdef STATIC_BUILD
void *fptr;
fptr = (void *)&SetExecname;
#else
int (*fptr)();
fptr = (int (*)())dlsym(RTLD_DEFAULT, "main"); fptr = (int (*)())dlsym(RTLD_DEFAULT, "main");
#endif
if (fptr == NULL) { if (fptr == NULL) {
JLI_ReportErrorMessage(DLL_ERROR3, dlerror()); JLI_ReportErrorMessage(DLL_ERROR3, dlerror());
return JNI_FALSE; return JNI_FALSE;

View File

@ -2184,10 +2184,10 @@ public class File
private static final long PATH_OFFSET; private static final long PATH_OFFSET;
private static final long PREFIX_LENGTH_OFFSET; private static final long PREFIX_LENGTH_OFFSET;
private static final sun.misc.Unsafe UNSAFE; private static final jdk.internal.misc.Unsafe UNSAFE;
static { static {
try { try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
PATH_OFFSET = unsafe.objectFieldOffset( PATH_OFFSET = unsafe.objectFieldOffset(
File.class.getDeclaredField("path")); File.class.getDeclaredField("path"));
PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset( PREFIX_LENGTH_OFFSET = unsafe.objectFieldOffset(

View File

@ -40,7 +40,7 @@ import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import static java.io.ObjectStreamClass.processQueue; import static java.io.ObjectStreamClass.processQueue;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import sun.reflect.misc.ReflectUtil; import sun.reflect.misc.ReflectUtil;
/** /**

View File

@ -48,7 +48,7 @@ import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import sun.reflect.CallerSensitive; import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.reflect.ReflectionFactory; import sun.reflect.ReflectionFactory;

View File

@ -31,6 +31,12 @@ import java.util.Spliterator;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.UTF16;
import static java.lang.String.LATIN1;
import static java.lang.String.checkIndex;
import static java.lang.String.checkOffset;
/** /**
* A mutable sequence of characters. * A mutable sequence of characters.
* <p> * <p>
@ -51,7 +57,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
/** /**
* The value is used for character storage. * The value is used for character storage.
*/ */
char[] value; byte[] value;
/**
* The id of the encoding used to encode the bytes in {@code value}.
*/
byte coder;
/** /**
* The count is the number of characters used. * The count is the number of characters used.
@ -68,7 +79,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* Creates an AbstractStringBuilder of the specified capacity. * Creates an AbstractStringBuilder of the specified capacity.
*/ */
AbstractStringBuilder(int capacity) { AbstractStringBuilder(int capacity) {
value = new char[capacity]; if (COMPACT_STRINGS) {
value = new byte[capacity];
coder = LATIN1;
} else {
value = StringUTF16.newBytesFor(capacity);
coder = UTF16;
}
} }
/** /**
@ -90,7 +107,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return the current capacity * @return the current capacity
*/ */
public int capacity() { public int capacity() {
return value.length; return value.length >> coder;
} }
/** /**
@ -110,9 +127,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @param minimumCapacity the minimum desired capacity. * @param minimumCapacity the minimum desired capacity.
*/ */
public void ensureCapacity(int minimumCapacity) { public void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > 0) if (minimumCapacity > 0) {
ensureCapacityInternal(minimumCapacity); ensureCapacityInternal(minimumCapacity);
} }
}
/** /**
* This method has the same contract as ensureCapacity, but is * This method has the same contract as ensureCapacity, but is
@ -120,24 +138,48 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
private void ensureCapacityInternal(int minimumCapacity) { private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code // overflow-conscious code
if (minimumCapacity - value.length > 0) int capacity = value.length >> coder;
if (minimumCapacity - capacity > 0) {
expandCapacity(minimumCapacity); expandCapacity(minimumCapacity);
} }
}
/** /**
* This implements the expansion semantics of ensureCapacity with no * This implements the expansion semantics of ensureCapacity with no
* size check or synchronization. * size check or synchronization.
*/ */
void expandCapacity(int minimumCapacity) { private void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2; int newCapacity = (value.length >> coder) * 2 + 2;
if (newCapacity - minimumCapacity < 0) if (newCapacity - minimumCapacity < 0) {
newCapacity = minimumCapacity; newCapacity = minimumCapacity;
}
if (newCapacity < 0) { if (newCapacity < 0) {
if (minimumCapacity < 0) // overflow if (minimumCapacity < 0) {// overflow
throw new OutOfMemoryError(); throw new OutOfMemoryError();
}
newCapacity = Integer.MAX_VALUE; newCapacity = Integer.MAX_VALUE;
} }
value = Arrays.copyOf(value, newCapacity); if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) {
if (minimumCapacity >= StringUTF16.MAX_LENGTH) {
throw new OutOfMemoryError();
}
newCapacity = StringUTF16.MAX_LENGTH;
}
this.value = Arrays.copyOf(value, newCapacity << coder);
}
/**
* If the coder is "isLatin1", this inflates the internal 8-bit storage
* to 16-bit <hi=0, low> pair storage.
*/
private void inflate() {
if (!isLatin1()) {
return;
}
byte[] buf = StringUTF16.newBytesFor(value.length);
StringLatin1.inflateSB(value, buf, 0, count);
this.value = buf;
this.coder = UTF16;
} }
/** /**
@ -148,8 +190,9 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* returned by a subsequent call to the {@link #capacity()} method. * returned by a subsequent call to the {@link #capacity()} method.
*/ */
public void trimToSize() { public void trimToSize() {
if (count < value.length) { int length = count << coder;
value = Arrays.copyOf(value, count); if (length < value.length) {
value = Arrays.copyOf(value, length);
} }
} }
@ -179,14 +222,17 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* {@code newLength} argument is negative. * {@code newLength} argument is negative.
*/ */
public void setLength(int newLength) { public void setLength(int newLength) {
if (newLength < 0) if (newLength < 0) {
throw new StringIndexOutOfBoundsException(newLength); throw new StringIndexOutOfBoundsException(newLength);
ensureCapacityInternal(newLength);
if (count < newLength) {
Arrays.fill(value, count, newLength, '\0');
} }
ensureCapacityInternal(newLength);
if (count < newLength) {
if (isLatin1()) {
StringLatin1.fillNull(value, count, newLength);
} else {
StringUTF16.fillNull(value, count, newLength);
}
}
count = newLength; count = newLength;
} }
@ -209,9 +255,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
@Override @Override
public char charAt(int index) { public char charAt(int index) {
if ((index < 0) || (index >= count)) checkIndex(index, count);
throw new StringIndexOutOfBoundsException(index); if (isLatin1()) {
return value[index]; return (char)(value[index] & 0xff);
}
return StringUTF16.charAt(value, index);
} }
/** /**
@ -236,10 +284,11 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* sequence. * sequence.
*/ */
public int codePointAt(int index) { public int codePointAt(int index) {
if ((index < 0) || (index >= count)) { checkIndex(index, count);
throw new StringIndexOutOfBoundsException(index); if (isLatin1()) {
return value[index] & 0xff;
} }
return Character.codePointAtImpl(value, index, count); return StringUTF16.codePointAtSB(value, index, count);
} }
/** /**
@ -265,10 +314,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
public int codePointBefore(int index) { public int codePointBefore(int index) {
int i = index - 1; int i = index - 1;
if ((i < 0) || (i >= count)) { if (i < 0 || i >= count) {
throw new StringIndexOutOfBoundsException(index); throw new StringIndexOutOfBoundsException(index);
} }
return Character.codePointBeforeImpl(value, index, 0); if (isLatin1()) {
return value[i] & 0xff;
}
return StringUTF16.codePointBeforeSB(value, index);
} }
/** /**
@ -295,7 +347,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex); if (isLatin1()) {
return endIndex - beginIndex;
}
return StringUTF16.codePointCountSB(value, beginIndex, endIndex);
} }
/** /**
@ -321,7 +376,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
if (index < 0 || index > count) { if (index < 0 || index > count) {
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
return Character.offsetByCodePointsImpl(value, 0, count, return Character.offsetByCodePoints(this,
index, codePointOffset); index, codePointOffset);
} }
@ -355,13 +410,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{ {
if (srcBegin < 0) checkRangeSIOOBE(srcBegin, srcEnd, count); // compatible to old version
throw new StringIndexOutOfBoundsException(srcBegin); int n = srcEnd - srcBegin;
if ((srcEnd < 0) || (srcEnd > count)) checkRange(dstBegin, dstBegin + n, dst.length);
throw new StringIndexOutOfBoundsException(srcEnd); if (isLatin1()) {
if (srcBegin > srcEnd) StringLatin1.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); } else {
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); StringUTF16.getCharsSB(value, srcBegin, srcEnd, dst, dstBegin);
}
} }
/** /**
@ -379,9 +435,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* negative or greater than or equal to {@code length()}. * negative or greater than or equal to {@code length()}.
*/ */
public void setCharAt(int index, char ch) { public void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count)) checkIndex(index, count);
throw new StringIndexOutOfBoundsException(index); if (isLatin1() && StringLatin1.canEncode(ch)) {
value[index] = ch; value[index] = (byte)ch;
} else {
if (isLatin1()) {
inflate();
}
StringUTF16.putCharSB(value, index, ch);
}
} }
/** /**
@ -418,35 +480,34 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return a reference to this object. * @return a reference to this object.
*/ */
public AbstractStringBuilder append(String str) { public AbstractStringBuilder append(String str) {
if (str == null) if (str == null) {
return appendNull(); return appendNull();
}
int len = str.length(); int len = str.length();
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
str.getChars(0, len, value, count); putStringAt(count, str);
count += len; count += len;
return this; return this;
} }
// Documentation in subclasses because of synchro difference // Documentation in subclasses because of synchro difference
public AbstractStringBuilder append(StringBuffer sb) { public AbstractStringBuilder append(StringBuffer sb) {
if (sb == null) return this.append((AbstractStringBuilder)sb);
return appendNull();
int len = sb.length();
ensureCapacityInternal(count + len);
sb.getChars(0, len, value, count);
count += len;
return this;
} }
/** /**
* @since 1.8 * @since 1.8
*/ */
AbstractStringBuilder append(AbstractStringBuilder asb) { AbstractStringBuilder append(AbstractStringBuilder asb) {
if (asb == null) if (asb == null) {
return appendNull(); return appendNull();
}
int len = asb.length(); int len = asb.length();
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
asb.getChars(0, len, value, count); if (getCoder() != asb.getCoder()) {
inflate();
}
asb.getBytes(value, count, coder);
count += len; count += len;
return this; return this;
} }
@ -454,25 +515,35 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
// Documentation in subclasses because of synchro difference // Documentation in subclasses because of synchro difference
@Override @Override
public AbstractStringBuilder append(CharSequence s) { public AbstractStringBuilder append(CharSequence s) {
if (s == null) if (s == null) {
return appendNull(); return appendNull();
if (s instanceof String) }
if (s instanceof String) {
return this.append((String)s); return this.append((String)s);
if (s instanceof AbstractStringBuilder) }
if (s instanceof AbstractStringBuilder) {
return this.append((AbstractStringBuilder)s); return this.append((AbstractStringBuilder)s);
}
return this.append(s, 0, s.length()); return this.append(s, 0, s.length());
} }
private AbstractStringBuilder appendNull() { private AbstractStringBuilder appendNull() {
int c = count; ensureCapacityInternal(count + 4);
ensureCapacityInternal(c + 4); int count = this.count;
final char[] value = this.value; byte[] val = this.value;
value[c++] = 'n'; if (isLatin1()) {
value[c++] = 'u'; val[count++] = 'n';
value[c++] = 'l'; val[count++] = 'u';
value[c++] = 'l'; val[count++] = 'l';
count = c; val[count++] = 'l';
} else {
checkOffset(count + 4, val.length >> 1);
StringUTF16.putChar(val, count++, 'n');
StringUTF16.putChar(val, count++, 'u');
StringUTF16.putChar(val, count++, 'l');
StringUTF16.putChar(val, count++, 'l');
}
this.count = count;
return this; return this;
} }
@ -507,21 +578,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
@Override @Override
public AbstractStringBuilder append(CharSequence s, int start, int end) { public AbstractStringBuilder append(CharSequence s, int start, int end) {
if (s == null) if (s == null) {
s = "null"; s = "null";
if ((start < 0) || (start > end) || (end > s.length())) }
throw new IndexOutOfBoundsException( checkRange(start, end, s.length());
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start; int len = end - start;
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
if (s instanceof String) { appendChars(s, start, end);
((String)s).getChars(start, end, value, count);
} else {
for (int i = start, j = count; i < end; i++, j++)
value[j] = s.charAt(i);
}
count += len;
return this; return this;
} }
@ -544,8 +607,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
public AbstractStringBuilder append(char[] str) { public AbstractStringBuilder append(char[] str) {
int len = str.length; int len = str.length;
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(str, 0, value, count, len); appendChars(str, 0, len);
count += len;
return this; return this;
} }
@ -572,10 +634,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* or {@code offset+len > str.length} * or {@code offset+len > str.length}
*/ */
public AbstractStringBuilder append(char str[], int offset, int len) { public AbstractStringBuilder append(char str[], int offset, int len) {
if (len > 0) // let arraycopy report AIOOBE for len < 0 int end = offset + len;
checkRange(offset, end, str.length);
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(str, offset, value, count, len); appendChars(str, offset, end);
count += len;
return this; return this;
} }
@ -592,20 +654,39 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return a reference to this object. * @return a reference to this object.
*/ */
public AbstractStringBuilder append(boolean b) { public AbstractStringBuilder append(boolean b) {
ensureCapacityInternal(count + (b ? 4 : 5));
int count = this.count;
byte[] val = this.value;
if (isLatin1()) {
if (b) { if (b) {
ensureCapacityInternal(count + 4); val[count++] = 't';
value[count++] = 't'; val[count++] = 'r';
value[count++] = 'r'; val[count++] = 'u';
value[count++] = 'u'; val[count++] = 'e';
value[count++] = 'e';
} else { } else {
ensureCapacityInternal(count + 5); val[count++] = 'f';
value[count++] = 'f'; val[count++] = 'a';
value[count++] = 'a'; val[count++] = 'l';
value[count++] = 'l'; val[count++] = 's';
value[count++] = 's'; val[count++] = 'e';
value[count++] = 'e';
} }
} else {
if (b) {
checkOffset(count + 4, val.length >> 1);
StringUTF16.putChar(val, count++, 't');
StringUTF16.putChar(val, count++, 'r');
StringUTF16.putChar(val, count++, 'u');
StringUTF16.putChar(val, count++, 'e');
} else {
checkOffset(count + 5, val.length >> 1);
StringUTF16.putChar(val, count++, 'f');
StringUTF16.putChar(val, count++, 'a');
StringUTF16.putChar(val, count++, 'l');
StringUTF16.putChar(val, count++, 's');
StringUTF16.putChar(val, count++, 'e');
}
}
this.count = count;
return this; return this;
} }
@ -627,7 +708,14 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
@Override @Override
public AbstractStringBuilder append(char c) { public AbstractStringBuilder append(char c) {
ensureCapacityInternal(count + 1); ensureCapacityInternal(count + 1);
value[count++] = c; if (isLatin1() && StringLatin1.canEncode(c)) {
value[count++] = (byte)c;
} else {
if (isLatin1()) {
inflate();
}
StringUTF16.putCharSB(value, count++, c);
}
return this; return this;
} }
@ -652,7 +740,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
: Integer.stringSize(i); : Integer.stringSize(i);
int spaceNeeded = count + appendedLength; int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded); ensureCapacityInternal(spaceNeeded);
if (isLatin1()) {
Integer.getChars(i, spaceNeeded, value); Integer.getChars(i, spaceNeeded, value);
} else {
byte[] val = this.value;
checkOffset(spaceNeeded, val.length >> 1);
Integer.getCharsUTF16(i, spaceNeeded, val);
}
count = spaceNeeded; count = spaceNeeded;
return this; return this;
} }
@ -678,7 +772,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
: Long.stringSize(l); : Long.stringSize(l);
int spaceNeeded = count + appendedLength; int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded); ensureCapacityInternal(spaceNeeded);
if (isLatin1()) {
Long.getChars(l, spaceNeeded, value); Long.getChars(l, spaceNeeded, value);
} else {
byte[] val = this.value;
checkOffset(spaceNeeded, val.length >> 1);
Long.getCharsUTF16(l, spaceNeeded, val);
}
count = spaceNeeded; count = spaceNeeded;
return this; return this;
} }
@ -732,15 +832,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than {@code end}. * greater than {@code end}.
*/ */
public AbstractStringBuilder delete(int start, int end) { public AbstractStringBuilder delete(int start, int end) {
if (start < 0) if (end > count) {
throw new StringIndexOutOfBoundsException(start);
if (end > count)
end = count; end = count;
if (start > end) }
throw new StringIndexOutOfBoundsException(); checkRangeSIOOBE(start, end, count);
int len = end - start; int len = end - start;
if (len > 0) { if (len > 0) {
System.arraycopy(value, start+len, value, start, count-end); shift(end, -len);
count -= len; count -= len;
} }
return this; return this;
@ -766,20 +864,10 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* {@code codePoint} isn't a valid Unicode code point * {@code codePoint} isn't a valid Unicode code point
*/ */
public AbstractStringBuilder appendCodePoint(int codePoint) { public AbstractStringBuilder appendCodePoint(int codePoint) {
final int count = this.count;
if (Character.isBmpCodePoint(codePoint)) { if (Character.isBmpCodePoint(codePoint)) {
ensureCapacityInternal(count + 1); return append((char)codePoint);
value[count] = (char) codePoint;
this.count = count + 1;
} else if (Character.isValidCodePoint(codePoint)) {
ensureCapacityInternal(count + 2);
Character.toSurrogates(codePoint, value, count);
this.count = count + 2;
} else {
throw new IllegalArgumentException();
} }
return this; return append(Character.toChars(codePoint));
} }
/** /**
@ -800,9 +888,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* {@code length()}. * {@code length()}.
*/ */
public AbstractStringBuilder deleteCharAt(int index) { public AbstractStringBuilder deleteCharAt(int index) {
if ((index < 0) || (index >= count)) checkIndex(index, count);
throw new StringIndexOutOfBoundsException(index); shift(index + 1, -1);
System.arraycopy(value, index+1, value, index, count-index-1);
count--; count--;
return this; return this;
} }
@ -827,22 +914,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than {@code end}. * greater than {@code end}.
*/ */
public AbstractStringBuilder replace(int start, int end, String str) { public AbstractStringBuilder replace(int start, int end, String str) {
if (start < 0) if (end > count) {
throw new StringIndexOutOfBoundsException(start);
if (start > count)
throw new StringIndexOutOfBoundsException("start > length()");
if (start > end)
throw new StringIndexOutOfBoundsException("start > end");
if (end > count)
end = count; end = count;
}
checkRangeSIOOBE(start, end, count);
int len = str.length(); int len = str.length();
int newCount = count + len - (end - start); int newCount = count + len - (end - start);
ensureCapacityInternal(newCount); ensureCapacityInternal(newCount);
shift(end, newCount - count);
System.arraycopy(value, end, value, start + len, count - end);
str.getChars(value, start);
count = newCount; count = newCount;
putStringAt(start, str);
return this; return this;
} }
@ -907,13 +988,16 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* greater than {@code end}. * greater than {@code end}.
*/ */
public String substring(int start, int end) { public String substring(int start, int end) {
if (start < 0) checkRangeSIOOBE(start, end, count);
throw new StringIndexOutOfBoundsException(start); if (isLatin1()) {
if (end > count) return StringLatin1.newString(value, start, end - start);
throw new StringIndexOutOfBoundsException(end); }
if (start > end) return StringUTF16.newStringSB(value, start, end - start);
throw new StringIndexOutOfBoundsException(end - start); }
return new String(value, start, end - start);
private void shift(int offset, int n) {
System.arraycopy(value, offset << coder,
value, (offset + n) << coder, (count - offset) << coder);
} }
/** /**
@ -940,16 +1024,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
public AbstractStringBuilder insert(int index, char[] str, int offset, public AbstractStringBuilder insert(int index, char[] str, int offset,
int len) int len)
{ {
if ((index < 0) || (index > length())) checkOffset(index, count);
throw new StringIndexOutOfBoundsException(index); checkRangeSIOOBE(offset, offset + len, str.length);
if ((offset < 0) || (len < 0) || (offset > str.length - len))
throw new StringIndexOutOfBoundsException(
"offset " + offset + ", len " + len + ", str.length "
+ str.length);
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(value, index, value, index + len, count - index); shift(index, len);
System.arraycopy(str, offset, value, index, len);
count += len; count += len;
putCharsAt(index, str, offset, offset + len);
return this; return this;
} }
@ -1008,15 +1088,15 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @throws StringIndexOutOfBoundsException if the offset is invalid. * @throws StringIndexOutOfBoundsException if the offset is invalid.
*/ */
public AbstractStringBuilder insert(int offset, String str) { public AbstractStringBuilder insert(int offset, String str) {
if ((offset < 0) || (offset > length())) checkOffset(offset, count);
throw new StringIndexOutOfBoundsException(offset); if (str == null) {
if (str == null)
str = "null"; str = "null";
}
int len = str.length(); int len = str.length();
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset); shift(offset, len);
str.getChars(value, offset);
count += len; count += len;
putStringAt(offset, str);
return this; return this;
} }
@ -1045,13 +1125,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @throws StringIndexOutOfBoundsException if the offset is invalid. * @throws StringIndexOutOfBoundsException if the offset is invalid.
*/ */
public AbstractStringBuilder insert(int offset, char[] str) { public AbstractStringBuilder insert(int offset, char[] str) {
if ((offset < 0) || (offset > length())) checkOffset(offset, count);
throw new StringIndexOutOfBoundsException(offset);
int len = str.length; int len = str.length;
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(value, offset, value, offset + len, count - offset); shift(offset, len);
System.arraycopy(str, 0, value, offset, len);
count += len; count += len;
putCharsAt(offset, str, 0, len);
return this; return this;
} }
@ -1077,10 +1156,12 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @throws IndexOutOfBoundsException if the offset is invalid. * @throws IndexOutOfBoundsException if the offset is invalid.
*/ */
public AbstractStringBuilder insert(int dstOffset, CharSequence s) { public AbstractStringBuilder insert(int dstOffset, CharSequence s) {
if (s == null) if (s == null) {
s = "null"; s = "null";
if (s instanceof String) }
if (s instanceof String) {
return this.insert(dstOffset, (String)s); return this.insert(dstOffset, (String)s);
}
return this.insert(dstOffset, s, 0, s.length()); return this.insert(dstOffset, s, 0, s.length());
} }
@ -1129,22 +1210,18 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* {@code end} is greater than {@code s.length()} * {@code end} is greater than {@code s.length()}
*/ */
public AbstractStringBuilder insert(int dstOffset, CharSequence s, public AbstractStringBuilder insert(int dstOffset, CharSequence s,
int start, int end) { int start, int end)
if (s == null) {
if (s == null) {
s = "null"; s = "null";
if ((dstOffset < 0) || (dstOffset > this.length())) }
throw new IndexOutOfBoundsException("dstOffset "+dstOffset); checkOffset(dstOffset, count);
if ((start < 0) || (end < 0) || (start > end) || (end > s.length())) checkRange(start, end, s.length());
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", s.length() "
+ s.length());
int len = end - start; int len = end - start;
ensureCapacityInternal(count + len); ensureCapacityInternal(count + len);
System.arraycopy(value, dstOffset, value, dstOffset + len, shift(dstOffset, len);
count - dstOffset);
for (int i=start; i<end; i++)
value[dstOffset++] = s.charAt(i);
count += len; count += len;
putCharsAt(dstOffset, s, start, end);
return this; return this;
} }
@ -1191,10 +1268,18 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @throws IndexOutOfBoundsException if the offset is invalid. * @throws IndexOutOfBoundsException if the offset is invalid.
*/ */
public AbstractStringBuilder insert(int offset, char c) { public AbstractStringBuilder insert(int offset, char c) {
checkOffset(offset, count);
ensureCapacityInternal(count + 1); ensureCapacityInternal(count + 1);
System.arraycopy(value, offset, value, offset + 1, count - offset); shift(offset, 1);
value[offset] = c;
count += 1; count += 1;
if (isLatin1() && StringLatin1.canEncode(c)) {
value[offset] = (byte)c;
} else {
if (isLatin1()) {
inflate();
}
StringUTF16.putCharSB(value, offset, c);
}
return this; return this;
} }
@ -1326,7 +1411,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* or {@code -1} if there is no such occurrence. * or {@code -1} if there is no such occurrence.
*/ */
public int indexOf(String str, int fromIndex) { public int indexOf(String str, int fromIndex) {
return String.indexOf(value, 0, count, str, fromIndex); return String.indexOf(value, coder, count, str, fromIndex);
} }
/** /**
@ -1366,7 +1451,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* or {@code -1} if there is no such occurrence. * or {@code -1} if there is no such occurrence.
*/ */
public int lastIndexOf(String str, int fromIndex) { public int lastIndexOf(String str, int fromIndex) {
return String.lastIndexOf(value, 0, count, str, fromIndex); return String.lastIndexOf(value, coder, count, str, fromIndex);
} }
/** /**
@ -1392,34 +1477,47 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
* @return a reference to this object. * @return a reference to this object.
*/ */
public AbstractStringBuilder reverse() { public AbstractStringBuilder reverse() {
boolean hasSurrogates = false; byte[] val = this.value;
int count = this.count;
int coder = this.coder;
int n = count - 1; int n = count - 1;
if (COMPACT_STRINGS && coder == LATIN1) {
for (int j = (n-1) >> 1; j >= 0; j--) { for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j; int k = n - j;
char cj = value[j]; byte cj = val[j];
char ck = value[k]; val[j] = val[k];
value[j] = ck; val[k] = cj;
value[k] = cj; }
} else {
checkOffset(count, val.length >> 1);
boolean hasSurrogates = false;
for (int j = (n-1) >> 1; j >= 0; j--) {
int k = n - j;
char cj = StringUTF16.getChar(val, j);
char ck = StringUTF16.getChar(val, k);
StringUTF16.putChar(val, j, ck);
StringUTF16.putChar(val, k, cj);
if (Character.isSurrogate(cj) || if (Character.isSurrogate(cj) ||
Character.isSurrogate(ck)) { Character.isSurrogate(ck)) {
hasSurrogates = true; hasSurrogates = true;
} }
} }
if (hasSurrogates) { if (hasSurrogates) {
reverseAllValidSurrogatePairs(); reverseAllValidSurrogatePairs(val, count);
}
} }
return this; return this;
} }
/** Outlined helper method for reverse() */ /** Outlined helper method for reverse() */
private void reverseAllValidSurrogatePairs() { private void reverseAllValidSurrogatePairs(byte[] val, int count) {
for (int i = 0; i < count - 1; i++) { for (int i = 0; i < count - 1; i++) {
char c2 = value[i]; char c2 = StringUTF16.getChar(val, i);
if (Character.isLowSurrogate(c2)) { if (Character.isLowSurrogate(c2)) {
char c1 = value[i + 1]; char c1 = StringUTF16.getChar(val, i + 1);
if (Character.isHighSurrogate(c1)) { if (Character.isHighSurrogate(c1)) {
value[i++] = c1; StringUTF16.putChar(val, i++, c1);
value[i] = c2; StringUTF16.putChar(val, i, c2);
} }
} }
} }
@ -1444,10 +1542,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
@Override @Override
public IntStream chars() { public IntStream chars() {
byte[] val = this.value; int count = this.count; byte coder = this.coder;
checkOffset(count, val.length >> coder);
// Reuse String-based spliterator. This requires a supplier to // Reuse String-based spliterator. This requires a supplier to
// capture the value and count when the terminal operation is executed // capture the value and count when the terminal operation is executed
return StreamSupport.intStream( return StreamSupport.intStream(
() -> new String.IntCharArraySpliterator(value, 0, count, 0), () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
: new StringUTF16.CharsSpliterator(val, 0, count, 0),
Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED, Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
false); false);
} }
@ -1458,10 +1559,13 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
*/ */
@Override @Override
public IntStream codePoints() { public IntStream codePoints() {
byte[] val = this.value; int count = this.count; byte coder = this.coder;
checkOffset(count, val.length >> coder);
// Reuse String-based spliterator. This requires a supplier to // Reuse String-based spliterator. This requires a supplier to
// capture the value and count when the terminal operation is executed // capture the value and count when the terminal operation is executed
return StreamSupport.intStream( return StreamSupport.intStream(
() -> new String.CodePointsSpliterator(value, 0, count, 0), () -> coder == LATIN1 ? new StringLatin1.CharsSpliterator(val, 0, count, 0)
: new StringUTF16.CodePointsSpliterator(val, 0, count, 0),
Spliterator.ORDERED, Spliterator.ORDERED,
false); false);
} }
@ -1469,8 +1573,147 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
/** /**
* Needed by {@code String} for the contentEquals method. * Needed by {@code String} for the contentEquals method.
*/ */
final char[] getValue() { final byte[] getValue() {
return value; return value;
} }
/*
* Invoker guarantees it is in UTF16 (inflate itself for asb), if two
* coders are different and the dstBegin has enough space
*
* @param dstBegin the char index, not offset of byte[]
* @param coder the coder of dst[]
*/
protected void getBytes(byte dst[], int dstBegin, byte coder) {
if (this.coder == coder) {
System.arraycopy(value, 0, dst, dstBegin << coder, count << coder);
} else { // this.coder == LATIN && coder == UTF16
StringLatin1.inflateSB(value, dst, dstBegin, count);
}
}
/* for readObject() */
protected void initBytes(char[] value, int off, int len) {
if (String.COMPACT_STRINGS) {
this.value = StringUTF16.compress(value, off, len);
if (this.value != null) {
this.coder = LATIN1;
return;
}
}
this.coder = UTF16;
this.value = StringUTF16.toBytes(value, off, len);
}
final byte getCoder() {
return COMPACT_STRINGS ? coder : UTF16;
}
final boolean isLatin1() {
return COMPACT_STRINGS && coder == LATIN1;
}
private final void putCharsAt(int index, char[] s, int off, int end) {
if (isLatin1()) {
byte[] val = this.value;
for (int i = off, j = index; i < end; i++) {
char c = s[i];
if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c;
} else {
inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end);
return;
}
}
} else {
StringUTF16.putCharsSB(this.value, index, s, off, end);
}
}
private final void putCharsAt(int index, CharSequence s, int off, int end) {
if (isLatin1()) {
byte[] val = this.value;
for (int i = off, j = index; i < end; i++) {
char c = s.charAt(i);
if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c;
} else {
inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end);
return;
}
}
} else {
StringUTF16.putCharsSB(this.value, index, s, off, end);
}
}
private final void putStringAt(int index, String str) {
if (getCoder() != str.coder()) {
inflate();
}
byte[] val = this.value;
byte coder = this.coder;
checkOffset(index + str.length(), val.length >> coder);
str.getBytes(val, index, coder);
}
private final void appendChars(char[] s, int off, int end) {
if (isLatin1()) {
byte[] val = this.value;
for (int i = off, j = count; i < end; i++) {
char c = s[i];
if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c;
} else {
count = j;
inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end);
count += end - i;
return;
}
}
} else {
StringUTF16.putCharsSB(this.value, count, s, off, end);
}
count += end - off;
}
private final void appendChars(CharSequence s, int off, int end) {
if (isLatin1()) {
byte[] val = this.value;
for (int i = off, j = count; i < end; i++) {
char c = s.charAt(i);
if (StringLatin1.canEncode(c)) {
val[j++] = (byte)c;
} else {
count = j;
inflate();
StringUTF16.putCharsSB(this.value, j, s, i, end);
count += end - i;
return;
}
}
} else {
StringUTF16.putCharsSB(this.value, count, s, off, end);
}
count += end - off;
}
/* IndexOutOfBoundsException, if out of bounds */
private static void checkRange(int start, int end, int len) {
if (start < 0 || start > end || end > len) {
throw new IndexOutOfBoundsException(
"start " + start + ", end " + end + ", length " + len);
}
}
/* StringIndexOutOfBoundsException, if out of bounds */
private static void checkRangeSIOOBE(int start, int end, int len) {
if (start < 0 || start > end || end > len) {
throw new StringIndexOutOfBoundsException(
"start " + start + ", end " + end + ", length " + len);
}
}
} }

View File

@ -55,7 +55,7 @@ import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import java.util.StringJoiner; import java.util.StringJoiner;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.HotSpotIntrinsicCandidate;
import sun.reflect.CallerSensitive; import sun.reflect.CallerSensitive;
import sun.reflect.ConstantPool; import sun.reflect.ConstantPool;

View File

@ -29,6 +29,10 @@ import java.lang.annotation.Native;
import java.util.Objects; import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.HotSpotIntrinsicCandidate;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
/** /**
* The {@code Integer} class wraps a value of the primitive type * The {@code Integer} class wraps a value of the primitive type
* {@code int} in an object. An object of type {@code Integer} * {@code int} in an object. An object of type {@code Integer}
@ -138,7 +142,8 @@ public final class Integer extends Number implements Comparable<Integer> {
return toString(i); return toString(i);
} }
char buf[] = new char[33]; if (COMPACT_STRINGS) {
byte[] buf = new byte[33];
boolean negative = (i < 0); boolean negative = (i < 0);
int charPos = 32; int charPos = 32;
@ -147,16 +152,37 @@ public final class Integer extends Number implements Comparable<Integer> {
} }
while (i <= -radix) { while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)]; buf[charPos--] = (byte)digits[-(i % radix)];
i = i / radix; i = i / radix;
} }
buf[charPos] = digits[-i]; buf[charPos] = (byte)digits[-i];
if (negative) { if (negative) {
buf[--charPos] = '-'; buf[--charPos] = '-';
} }
return new String(buf, charPos, (33 - charPos)); return StringLatin1.newString(buf, charPos, (33 - charPos));
}
return toStringUTF16(i, radix);
}
private static String toStringUTF16(int i, int radix) {
byte[] buf = new byte[33 * 2];
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i;
}
while (i <= -radix) {
StringUTF16.putChar(buf, charPos--, digits[-(i % radix)]);
i = i / radix;
}
StringUTF16.putChar(buf, charPos, digits[-i]);
if (negative) {
StringUTF16.putChar(buf, --charPos, '-');
}
return StringUTF16.newString(buf, charPos, (33 - charPos));
} }
/** /**
@ -312,12 +338,16 @@ public final class Integer extends Number implements Comparable<Integer> {
// assert shift > 0 && shift <=5 : "Illegal shift value"; // assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
int chars = Math.max(((mag + (shift - 1)) / shift), 1); int chars = Math.max(((mag + (shift - 1)) / shift), 1);
char[] buf = new char[chars];
if (COMPACT_STRINGS) {
byte[] buf = new byte[chars];
formatUnsignedInt(val, shift, buf, 0, chars); formatUnsignedInt(val, shift, buf, 0, chars);
return new String(buf, LATIN1);
// Use special constructor which takes over "buf". } else {
return new String(buf, true); byte[] buf = new byte[chars * 2];
formatUnsignedIntUTF16(val, shift, buf, 0, chars);
return new String(buf, UTF16);
}
} }
/** /**
@ -344,6 +374,28 @@ public final class Integer extends Number implements Comparable<Integer> {
} while (charPos > offset); } while (charPos > offset);
} }
/** byte[]/LATIN1 version */
static void formatUnsignedInt(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = (byte)Integer.digits[val & mask];
val >>>= shift;
} while (charPos > offset);
}
/** byte[]/UTF16 version */
static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]);
val >>>= shift;
} while (charPos > offset);
}
static final char [] DigitTens = { static final char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
@ -401,9 +453,15 @@ public final class Integer extends Number implements Comparable<Integer> {
if (i == Integer.MIN_VALUE) if (i == Integer.MIN_VALUE)
return "-2147483648"; return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size]; if (COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf); getChars(i, size, buf);
return new String(buf, true); return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
getCharsUTF16(i, size, buf);
return new String(buf, UTF16);
}
} }
/** /**
@ -433,7 +491,7 @@ public final class Integer extends Number implements Comparable<Integer> {
* *
* Will fail if i == Integer.MIN_VALUE * Will fail if i == Integer.MIN_VALUE
*/ */
static void getChars(int i, int index, char[] buf) { static void getChars(int i, int index, byte[] buf) {
int q, r; int q, r;
int charPos = index; int charPos = index;
char sign = 0; char sign = 0;
@ -449,8 +507,8 @@ public final class Integer extends Number implements Comparable<Integer> {
// really: r = i - (q * 100); // really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2)); r = i - ((q << 6) + (q << 5) + (q << 2));
i = q; i = q;
buf [--charPos] = DigitOnes[r]; buf [--charPos] = (byte)DigitOnes[r];
buf [--charPos] = DigitTens[r]; buf [--charPos] = (byte)DigitTens[r];
} }
// Fall thru to fast mode for smaller numbers // Fall thru to fast mode for smaller numbers
@ -458,12 +516,46 @@ public final class Integer extends Number implements Comparable<Integer> {
for (;;) { for (;;) {
q = (i * 52429) >>> (16+3); q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ... r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
buf [--charPos] = digits [r]; buf [--charPos] = (byte)digits [r];
i = q; i = q;
if (i == 0) break; if (i == 0) break;
} }
if (sign != 0) { if (sign != 0) {
buf [--charPos] = sign; buf [--charPos] = (byte)sign;
}
}
static void getCharsUTF16(int i, int index, byte[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Generate two digits per iteration
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
StringUTF16.putChar(buf, --charPos, DigitOnes[r]);
StringUTF16.putChar(buf, --charPos, DigitTens[r]);
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
i = q;
if (i == 0) break;
}
if (sign != 0) {
StringUTF16.putChar(buf, --charPos, sign);
} }
} }

View File

@ -30,6 +30,9 @@ import java.math.*;
import java.util.Objects; import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.HotSpotIntrinsicCandidate;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
/** /**
* The {@code Long} class wraps a value of the primitive type {@code * The {@code Long} class wraps a value of the primitive type {@code
@ -124,7 +127,9 @@ public final class Long extends Number implements Comparable<Long> {
radix = 10; radix = 10;
if (radix == 10) if (radix == 10)
return toString(i); return toString(i);
char[] buf = new char[65];
if (COMPACT_STRINGS) {
byte[] buf = new byte[65];
int charPos = 64; int charPos = 64;
boolean negative = (i < 0); boolean negative = (i < 0);
@ -133,16 +138,35 @@ public final class Long extends Number implements Comparable<Long> {
} }
while (i <= -radix) { while (i <= -radix) {
buf[charPos--] = Integer.digits[(int)(-(i % radix))]; buf[charPos--] = (byte)Integer.digits[(int)(-(i % radix))];
i = i / radix; i = i / radix;
} }
buf[charPos] = Integer.digits[(int)(-i)]; buf[charPos] = (byte)Integer.digits[(int)(-i)];
if (negative) { if (negative) {
buf[--charPos] = '-'; buf[--charPos] = '-';
} }
return StringLatin1.newString(buf, charPos, (65 - charPos));
}
return toStringUTF16(i, radix);
}
return new String(buf, charPos, (65 - charPos)); private static String toStringUTF16(long i, int radix) {
byte[] buf = new byte[65 * 2];
int charPos = 64;
boolean negative = (i < 0);
if (!negative) {
i = -i;
}
while (i <= -radix) {
StringUTF16.putChar(buf, charPos--, Integer.digits[(int)(-(i % radix))]);
i = i / radix;
}
StringUTF16.putChar(buf, charPos, Integer.digits[(int)(-i)]);
if (negative) {
StringUTF16.putChar(buf, --charPos, '-');
}
return StringUTF16.newString(buf, charPos, (65 - charPos));
} }
/** /**
@ -355,10 +379,16 @@ public final class Long extends Number implements Comparable<Long> {
// assert shift > 0 && shift <=5 : "Illegal shift value"; // assert shift > 0 && shift <=5 : "Illegal shift value";
int mag = Long.SIZE - Long.numberOfLeadingZeros(val); int mag = Long.SIZE - Long.numberOfLeadingZeros(val);
int chars = Math.max(((mag + (shift - 1)) / shift), 1); int chars = Math.max(((mag + (shift - 1)) / shift), 1);
char[] buf = new char[chars];
formatUnsignedLong(val, shift, buf, 0, chars); if (COMPACT_STRINGS) {
return new String(buf, true); byte[] buf = new byte[chars];
formatUnsignedLong0(val, shift, buf, 0, chars);
return new String(buf, LATIN1);
} else {
byte[] buf = new byte[chars * 2];
formatUnsignedLong0UTF16(val, shift, buf, 0, chars);
return new String(buf, UTF16);
}
} }
/** /**
@ -385,6 +415,28 @@ public final class Long extends Number implements Comparable<Long> {
} while (charPos > offset); } while (charPos > offset);
} }
/** byte[]/LATIN1 version */
static void formatUnsignedLong0(long val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = (byte)Integer.digits[((int) val) & mask];
val >>>= shift;
} while (charPos > offset);
}
/** byte[]/UTF16 version */
static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) {
int charPos = offset + len;
int radix = 1 << shift;
int mask = radix - 1;
do {
StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]);
val >>>= shift;
} while (charPos > offset);
}
/** /**
* Returns a {@code String} object representing the specified * Returns a {@code String} object representing the specified
* {@code long}. The argument is converted to signed decimal * {@code long}. The argument is converted to signed decimal
@ -399,9 +451,15 @@ public final class Long extends Number implements Comparable<Long> {
if (i == Long.MIN_VALUE) if (i == Long.MIN_VALUE)
return "-9223372036854775808"; return "-9223372036854775808";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size]; if (COMPACT_STRINGS) {
byte[] buf = new byte[size];
getChars(i, size, buf); getChars(i, size, buf);
return new String(buf, true); return new String(buf, LATIN1);
} else {
byte[] buf = new byte[size * 2];
getCharsUTF16(i, size, buf);
return new String(buf, UTF16);
}
} }
/** /**
@ -431,7 +489,7 @@ public final class Long extends Number implements Comparable<Long> {
* *
* Will fail if i == Long.MIN_VALUE * Will fail if i == Long.MIN_VALUE
*/ */
static void getChars(long i, int index, char[] buf) { static void getChars(long i, int index, byte[] buf) {
long q; long q;
int r; int r;
int charPos = index; int charPos = index;
@ -448,8 +506,8 @@ public final class Long extends Number implements Comparable<Long> {
// really: r = i - (q * 100); // really: r = i - (q * 100);
r = (int)(i - ((q << 6) + (q << 5) + (q << 2))); r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
i = q; i = q;
buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = (byte)Integer.DigitOnes[r];
buf[--charPos] = Integer.DigitTens[r]; buf[--charPos] = (byte)Integer.DigitTens[r];
} }
// Get 2 digits/iteration using ints // Get 2 digits/iteration using ints
@ -460,8 +518,8 @@ public final class Long extends Number implements Comparable<Long> {
// really: r = i2 - (q * 100); // really: r = i2 - (q * 100);
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2)); r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
i2 = q2; i2 = q2;
buf[--charPos] = Integer.DigitOnes[r]; buf[--charPos] = (byte)Integer.DigitOnes[r];
buf[--charPos] = Integer.DigitTens[r]; buf[--charPos] = (byte)Integer.DigitTens[r];
} }
// Fall thru to fast mode for smaller numbers // Fall thru to fast mode for smaller numbers
@ -469,12 +527,59 @@ public final class Long extends Number implements Comparable<Long> {
for (;;) { for (;;) {
q2 = (i2 * 52429) >>> (16+3); q2 = (i2 * 52429) >>> (16+3);
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ... r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
buf[--charPos] = Integer.digits[r]; buf[--charPos] = (byte)Integer.digits[r];
i2 = q2; i2 = q2;
if (i2 == 0) break; if (i2 == 0) break;
} }
if (sign != 0) { if (sign != 0) {
buf[--charPos] = sign; buf[--charPos] = (byte)sign;
}
}
static void getCharsUTF16(long i, int index, byte[] buf) {
long q;
int r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Get 2 digits/iteration using longs until quotient fits into an int
while (i > Integer.MAX_VALUE) {
q = i / 100;
// really: r = i - (q * 100);
r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
i = q;
StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
}
// Get 2 digits/iteration using ints
int q2;
int i2 = (int)i;
while (i2 >= 65536) {
q2 = i2 / 100;
// really: r = i2 - (q * 100);
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
i2 = q2;
StringUTF16.putChar(buf, --charPos, Integer.DigitOnes[r]);
StringUTF16.putChar(buf, --charPos, Integer.DigitTens[r]);
}
// Fall thru to fast mode for smaller numbers
// assert(i2 <= 65536, i2);
for (;;) {
q2 = (i2 * 52429) >>> (16+3);
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
StringUTF16.putChar(buf, --charPos, Integer.digits[r]);
i2 = q2;
if (i2 == 0) break;
}
if (sign != 0) {
StringUTF16.putChar(buf, --charPos, sign);
} }
} }

View File

@ -83,7 +83,7 @@ import java.util.stream.Stream;
* {@link #getPid() process id}, * {@link #getPid() process id},
* {@link #info() information about the process}, * {@link #info() information about the process},
* {@link #children() direct children}, and * {@link #children() direct children}, and
* {@link #allChildren() direct and indirect children} of the process. * {@link #descendants() direct children plus descendants of those children} of the process.
* Delegating to the underlying Process or ProcessHandle is typically * Delegating to the underlying Process or ProcessHandle is typically
* easiest and most efficient. * easiest and most efficient.
* *
@ -351,7 +351,7 @@ public abstract class Process {
* The {@link java.util.concurrent.CompletableFuture} provides the ability * The {@link java.util.concurrent.CompletableFuture} provides the ability
* to trigger dependent functions or actions that may be run synchronously * to trigger dependent functions or actions that may be run synchronously
* or asynchronously upon process termination. * or asynchronously upon process termination.
* When the process terminates the CompletableFuture is * When the process has terminated the CompletableFuture is
* {@link java.util.concurrent.CompletableFuture#complete completed} regardless * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
* of the exit status of the process. * of the exit status of the process.
* <p> * <p>
@ -362,9 +362,6 @@ public abstract class Process {
* {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling} * {@link java.util.concurrent.CompletableFuture#cancel(boolean) Cancelling}
* the CompletableFuture does not affect the Process. * the CompletableFuture does not affect the Process.
* <p> * <p>
* If the process is {@link #isAlive not alive} the {@link CompletableFuture}
* returned has been {@link java.util.concurrent.CompletableFuture#complete completed}.
* <p>
* Processes returned from {@link ProcessBuilder#start} override the * Processes returned from {@link ProcessBuilder#start} override the
* default implementation to provide an efficient mechanism to wait * default implementation to provide an efficient mechanism to wait
* for process exit. * for process exit.
@ -406,6 +403,9 @@ public abstract class Process {
* return delegate.onExit().thenApply(p -> this); * return delegate.onExit().thenApply(p -> this);
* } * }
* }</pre> * }</pre>
* @apiNote
* The process may be observed to have terminated with {@link #isAlive}
* before the ComputableFuture is completed and dependent actions are invoked.
* *
* @return a new {@code CompletableFuture<Process>} for the Process * @return a new {@code CompletableFuture<Process>} for the Process
* *
@ -464,7 +464,7 @@ public abstract class Process {
* {@link java.lang.UnsupportedOperationException} and performs no other action. * {@link java.lang.UnsupportedOperationException} and performs no other action.
* Subclasses should override this method to provide a ProcessHandle for the * Subclasses should override this method to provide a ProcessHandle for the
* process. The methods {@link #getPid}, {@link #info}, {@link #children}, * process. The methods {@link #getPid}, {@link #info}, {@link #children},
* and {@link #allChildren}, unless overridden, operate on the ProcessHandle. * and {@link #descendants}, unless overridden, operate on the ProcessHandle.
* *
* @return Returns a ProcessHandle for the Process * @return Returns a ProcessHandle for the Process
* @throws UnsupportedOperationException if the Process implementation * @throws UnsupportedOperationException if the Process implementation
@ -481,9 +481,8 @@ public abstract class Process {
/** /**
* Returns a snapshot of information about the process. * Returns a snapshot of information about the process.
* *
* <p> An {@link ProcessHandle.Info} instance has various accessor methods * <p> A {@link ProcessHandle.Info} instance has accessor methods
* that return information about the process, if the process is alive and * that return information about the process if it is available.
* the information is available, otherwise {@code null} is returned.
* *
* @implSpec * @implSpec
* This implementation returns information about the process as: * This implementation returns information about the process as:
@ -524,9 +523,9 @@ public abstract class Process {
} }
/** /**
* Returns a snapshot of the direct and indirect children of the process. * Returns a snapshot of the descendants of the process.
* An indirect child is one whose parent is either a direct child or * The descendants of a process are the children of the process
* another indirect child. * plus the descendants of those children, recursively.
* Typically, a process that is {@link #isAlive not alive} has no children. * Typically, a process that is {@link #isAlive not alive} has no children.
* <p> * <p>
* <em>Note that processes are created and terminate asynchronously. * <em>Note that processes are created and terminate asynchronously.
@ -535,18 +534,18 @@ public abstract class Process {
* *
* @implSpec * @implSpec
* This implementation returns all children as: * This implementation returns all children as:
* {@link #toHandle toHandle().allChildren()}. * {@link #toHandle toHandle().descendants()}.
* *
* @return a sequential Stream of ProcessHandles for processes that are * @return a sequential Stream of ProcessHandles for processes that
* direct and indirect children of the process * are descendants of the process
* @throws UnsupportedOperationException if the Process implementation * @throws UnsupportedOperationException if the Process implementation
* does not support this operation * does not support this operation
* @throws SecurityException if a security manager has been installed and * @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess") * it denies RuntimePermission("manageProcess")
* @since 1.9 * @since 1.9
*/ */
public Stream<ProcessHandle> allChildren() { public Stream<ProcessHandle> descendants() {
return toHandle().allChildren(); return toHandle().descendants();
} }

View File

@ -54,7 +54,7 @@ import java.util.stream.Stream;
* Each ProcessHandle identifies and allows control of a process in the native * Each ProcessHandle identifies and allows control of a process in the native
* system. ProcessHandles are returned from the factory methods {@link #current()}, * system. ProcessHandles are returned from the factory methods {@link #current()},
* {@link #of(long)}, * {@link #of(long)},
* {@link #children}, {@link #allChildren}, {@link #parent()} and * {@link #children}, {@link #descendants}, {@link #parent()} and
* {@link #allProcesses()}. * {@link #allProcesses()}.
* <p> * <p>
* The {@link Process} instances created by {@link ProcessBuilder} can be queried * The {@link Process} instances created by {@link ProcessBuilder} can be queried
@ -164,21 +164,21 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
Stream<ProcessHandle> children(); Stream<ProcessHandle> children();
/** /**
* Returns a snapshot of the current direct and indirect children of the process. * Returns a snapshot of the descendants of the process.
* An indirect child is one whose parent is either a direct child or * The descendants of a process are the children of the process
* another indirect child. * plus the descendants of those children, recursively.
* Typically, a process that is {@link #isAlive not alive} has no children. * Typically, a process that is {@link #isAlive not alive} has no children.
* <p> * <p>
* <em>Note that processes are created and terminate asynchronously. * <em>Note that processes are created and terminate asynchronously.
* There is no guarantee that a process is {@link #isAlive alive}. * There is no guarantee that a process is {@link #isAlive alive}.
* </em> * </em>
* *
* @return a sequential Stream of ProcessHandles for processes that are * @return a sequential Stream of ProcessHandles for processes that
* direct and indirect children of the process * are descendants of the process
* @throws SecurityException if a security manager has been installed and * @throws SecurityException if a security manager has been installed and
* it denies RuntimePermission("manageProcess") * it denies RuntimePermission("manageProcess")
*/ */
Stream<ProcessHandle> allChildren(); Stream<ProcessHandle> descendants();
/** /**
* Returns a snapshot of all processes visible to the current process. * Returns a snapshot of all processes visible to the current process.
@ -201,9 +201,8 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
/** /**
* Returns a snapshot of information about the process. * Returns a snapshot of information about the process.
* *
* <p> An {@code Info} instance has various accessor methods that return * <p> A {@link ProcessHandle.Info} instance has accessor methods that return
* information about the process, if the process is alive and the * information about the process if it is available.
* information is available.
* *
* @return a snapshot of information about the process, always non-null * @return a snapshot of information about the process, always non-null
*/ */
@ -288,7 +287,7 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
* The {@link java.util.concurrent.CompletableFuture} provides the ability * The {@link java.util.concurrent.CompletableFuture} provides the ability
* to trigger dependent functions or actions that may be run synchronously * to trigger dependent functions or actions that may be run synchronously
* or asynchronously upon process termination. * or asynchronously upon process termination.
* When the process terminates the CompletableFuture is * When the process has terminated the CompletableFuture is
* {@link java.util.concurrent.CompletableFuture#complete completed} regardless * {@link java.util.concurrent.CompletableFuture#complete completed} regardless
* of the exit status of the process. * of the exit status of the process.
* The {@code onExit} method can be called multiple times to invoke * The {@code onExit} method can be called multiple times to invoke
@ -300,9 +299,9 @@ public interface ProcessHandle extends Comparable<ProcessHandle> {
* {@link java.util.concurrent.Future#get() wait} for it to terminate. * {@link java.util.concurrent.Future#get() wait} for it to terminate.
* {@link java.util.concurrent.Future#cancel(boolean) Cancelling} * {@link java.util.concurrent.Future#cancel(boolean) Cancelling}
* the CompleteableFuture does not affect the Process. * the CompleteableFuture does not affect the Process.
* <p> * @apiNote
* If the process is {@link #isAlive not alive} the {@link CompletableFuture} * The process may be observed to have terminated with {@link #isAlive}
* returned has been {@link java.util.concurrent.CompletableFuture#complete completed}. * before the ComputableFuture is completed and dependent actions are invoked.
* *
* @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle * @return a new {@code CompletableFuture<ProcessHandle>} for the ProcessHandle
* *

View File

@ -389,7 +389,7 @@ final class ProcessHandleImpl implements ProcessHandle {
} }
@Override @Override
public Stream<ProcessHandle> allChildren() { public Stream<ProcessHandle> descendants() {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
sm.checkPermission(new RuntimePermission("manageProcess")); sm.checkPermission(new RuntimePermission("manageProcess"));

File diff suppressed because it is too large Load Diff

View File

@ -104,7 +104,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
* A cache of the last value returned by toString. Cleared * A cache of the last value returned by toString. Cleared
* whenever the StringBuffer is modified. * whenever the StringBuffer is modified.
*/ */
private transient char[] toStringCache; private transient String toStringCache;
/** use serialVersionUID from JDK 1.0.2 for interoperability */ /** use serialVersionUID from JDK 1.0.2 for interoperability */
static final long serialVersionUID = 3388685877147921107L; static final long serialVersionUID = 3388685877147921107L;
@ -169,15 +169,13 @@ import jdk.internal.HotSpotIntrinsicCandidate;
@Override @Override
public synchronized int capacity() { public synchronized int capacity() {
return value.length; return super.capacity();
} }
@Override @Override
public synchronized void ensureCapacity(int minimumCapacity) { public synchronized void ensureCapacity(int minimumCapacity) {
if (minimumCapacity > value.length) { super.ensureCapacity(minimumCapacity);
expandCapacity(minimumCapacity);
}
} }
/** /**
@ -204,9 +202,7 @@ import jdk.internal.HotSpotIntrinsicCandidate;
*/ */
@Override @Override
public synchronized char charAt(int index) { public synchronized char charAt(int index) {
if ((index < 0) || (index >= count)) return super.charAt(index);
throw new StringIndexOutOfBoundsException(index);
return value[index];
} }
/** /**
@ -261,10 +257,8 @@ import jdk.internal.HotSpotIntrinsicCandidate;
*/ */
@Override @Override
public synchronized void setCharAt(int index, char ch) { public synchronized void setCharAt(int index, char ch) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
toStringCache = null; toStringCache = null;
value[index] = ch; super.setCharAt(index, ch);
} }
@Override @Override
@ -680,9 +674,11 @@ import jdk.internal.HotSpotIntrinsicCandidate;
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public synchronized String toString() { public synchronized String toString() {
if (toStringCache == null) { if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count); return toStringCache =
isLatin1() ? StringLatin1.newString(value, 0, count)
: StringUTF16.newString(value, 0, count);
} }
return new String(toStringCache, true); return new String(toStringCache);
} }
/** /**
@ -710,7 +706,13 @@ import jdk.internal.HotSpotIntrinsicCandidate;
private synchronized void writeObject(java.io.ObjectOutputStream s) private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException { throws java.io.IOException {
java.io.ObjectOutputStream.PutField fields = s.putFields(); java.io.ObjectOutputStream.PutField fields = s.putFields();
fields.put("value", value); char[] val = new char[capacity()];
if (isLatin1()) {
StringLatin1.getChars(value, 0, count, val, 0);
} else {
StringUTF16.getChars(value, 0, count, val, 0);
}
fields.put("value", val);
fields.put("count", count); fields.put("count", count);
fields.put("shared", false); fields.put("shared", false);
s.writeFields(); s.writeFields();
@ -723,7 +725,12 @@ import jdk.internal.HotSpotIntrinsicCandidate;
private void readObject(java.io.ObjectInputStream s) private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
java.io.ObjectInputStream.GetField fields = s.readFields(); java.io.ObjectInputStream.GetField fields = s.readFields();
value = (char[])fields.get("value", null); char[] val = (char[])fields.get("value", null);
initBytes(val, 0, val.length);
count = fields.get("count", 0); count = fields.get("count", 0);
} }
protected synchronized void getBytes(byte dst[], int dstBegin, byte coder) {
super.getBytes(dst, dstBegin, coder);
}
} }

View File

@ -412,7 +412,8 @@ public final class StringBuilder
@HotSpotIntrinsicCandidate @HotSpotIntrinsicCandidate
public String toString() { public String toString() {
// Create a copy, don't share the array // Create a copy, don't share the array
return new String(value, 0, count); return isLatin1() ? StringLatin1.newString(value, 0, count)
: StringUTF16.newStringSB(value, 0, count);
} }
/** /**
@ -430,7 +431,13 @@ public final class StringBuilder
throws java.io.IOException { throws java.io.IOException {
s.defaultWriteObject(); s.defaultWriteObject();
s.writeInt(count); s.writeInt(count);
s.writeObject(value); char[] val = new char[capacity()];
if (isLatin1()) {
StringLatin1.getChars(value, 0, count, val, 0);
} else {
StringUTF16.getChars(value, 0, count, val, 0);
}
s.writeObject(val);
} }
/** /**
@ -441,7 +448,8 @@ public final class StringBuilder
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject(); s.defaultReadObject();
count = s.readInt(); count = s.readInt();
value = (char[]) s.readObject(); char[] val = (char[]) s.readObject();
initBytes(val, 0, val.length);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -38,11 +38,19 @@ import java.nio.charset.CodingErrorAction;
import java.nio.charset.IllegalCharsetNameException; import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.Arrays; import java.util.Arrays;
import jdk.internal.HotSpotIntrinsicCandidate;
import sun.misc.MessageUtils; import sun.misc.MessageUtils;
import sun.nio.cs.HistoricallyNamedCharset; import sun.nio.cs.HistoricallyNamedCharset;
import sun.nio.cs.ArrayDecoder; import sun.nio.cs.ArrayDecoder;
import sun.nio.cs.ArrayEncoder; import sun.nio.cs.ArrayEncoder;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.COMPACT_STRINGS;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.US_ASCII;
import static java.nio.charset.StandardCharsets.UTF_8;
/** /**
* Utility class for string encoding and decoding. * Utility class for string encoding and decoding.
*/ */
@ -72,23 +80,13 @@ class StringCoding {
// Trim the given byte array to the given length // Trim the given byte array to the given length
// //
private static byte[] safeTrim(byte[] ba, int len, Charset cs, boolean isTrusted) { private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) {
if (len == ba.length && (isTrusted || System.getSecurityManager() == null)) if (len == ba.length && (isTrusted || System.getSecurityManager() == null))
return ba; return ba;
else else
return Arrays.copyOf(ba, len); return Arrays.copyOf(ba, len);
} }
// Trim the given char array to the given length
//
private static char[] safeTrim(char[] ca, int len,
Charset cs, boolean isTrusted) {
if (len == ca.length && (isTrusted || System.getSecurityManager() == null))
return ca;
else
return Arrays.copyOf(ca, len);
}
private static int scale(int len, float expansionFactor) { private static int scale(int len, float expansionFactor) {
// We need to perform double, not float, arithmetic; otherwise // We need to perform double, not float, arithmetic; otherwise
// we lose low order bits when len is larger than 2**24. // we lose low order bits when len is larger than 2**24.
@ -117,21 +115,64 @@ class StringCoding {
} }
} }
static class Result {
byte[] value;
byte coder;
Result with() {
coder = COMPACT_STRINGS ? LATIN1 : UTF16;
value = new byte[0];
return this;
}
Result with(char[] val, int off, int len) {
if (String.COMPACT_STRINGS) {
byte[] bs = StringUTF16.compress(val, off, len);
if (bs != null) {
value = bs;
coder = LATIN1;
return this;
}
}
coder = UTF16;
value = StringUTF16.toBytes(val, off, len);
return this;
}
Result with(byte[] val, byte coder) {
this.coder = coder;
value = val;
return this;
}
}
@HotSpotIntrinsicCandidate
private static boolean hasNegatives(byte[] ba, int off, int len) {
for (int i = off; i < off + len; i++) {
if (ba[i] < 0) {
return true;
}
}
return false;
}
// -- Decoding -- // -- Decoding --
private static class StringDecoder { static class StringDecoder {
private final String requestedCharsetName; private final String requestedCharsetName;
private final Charset cs; private final Charset cs;
private final boolean isASCIICompatible;
private final CharsetDecoder cd; private final CharsetDecoder cd;
private final boolean isTrusted; protected final Result result;
private StringDecoder(Charset cs, String rcn) { StringDecoder(Charset cs, String rcn) {
this.requestedCharsetName = rcn; this.requestedCharsetName = rcn;
this.cs = cs; this.cs = cs;
this.cd = cs.newDecoder() this.cd = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE) .onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE); .onUnmappableCharacter(CodingErrorAction.REPLACE);
this.isTrusted = (cs.getClass().getClassLoader0() == null); this.result = new Result();
this.isASCIICompatible = (cd instanceof ArrayDecoder) &&
((ArrayDecoder)cd).isASCIICompatible();
} }
String charsetName() { String charsetName() {
@ -144,15 +185,25 @@ class StringCoding {
return requestedCharsetName; return requestedCharsetName;
} }
char[] decode(byte[] ba, int off, int len) { Result decode(byte[] ba, int off, int len) {
if (len == 0) {
return result.with();
}
// fastpath for ascii compatible
if (isASCIICompatible && !hasNegatives(ba, off, len)) {
if (COMPACT_STRINGS) {
return result.with(Arrays.copyOfRange(ba, off, off + len),
LATIN1);
} else {
return result.with(StringLatin1.inflate(ba, off, len), UTF16);
}
}
int en = scale(len, cd.maxCharsPerByte()); int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en]; char[] ca = new char[en];
if (len == 0)
return ca;
if (cd instanceof ArrayDecoder) { if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca); int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted); return result.with(ca, 0, clen);
} else { }
cd.reset(); cd.reset();
ByteBuffer bb = ByteBuffer.wrap(ba, off, len); ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
CharBuffer cb = CharBuffer.wrap(ca); CharBuffer cb = CharBuffer.wrap(ca);
@ -168,12 +219,24 @@ class StringCoding {
// so this shouldn't happen // so this shouldn't happen
throw new Error(x); throw new Error(x);
} }
return safeTrim(ca, cb.position(), cs, isTrusted); return result.with(ca, 0, cb.position());
}
}
private static class StringDecoder8859_1 extends StringDecoder {
StringDecoder8859_1(Charset cs, String rcn) {
super(cs, rcn);
}
Result decode(byte[] ba, int off, int len) {
if (COMPACT_STRINGS) {
return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
} else {
return result.with(StringLatin1.inflate(ba, off, len), UTF16);
} }
} }
} }
static char[] decode(String charsetName, byte[] ba, int off, int len) static Result decode(String charsetName, byte[] ba, int off, int len)
throws UnsupportedEncodingException throws UnsupportedEncodingException
{ {
StringDecoder sd = deref(decoder); StringDecoder sd = deref(decoder);
@ -183,8 +246,15 @@ class StringCoding {
sd = null; sd = null;
try { try {
Charset cs = lookupCharset(csn); Charset cs = lookupCharset(csn);
if (cs != null) if (cs != null) {
if (cs == UTF_8) {
sd = new StringDecoderUTF8(cs, csn);
} else if (cs == ISO_8859_1) {
sd = new StringDecoder8859_1(cs, csn);
} else {
sd = new StringDecoder(cs, csn); sd = new StringDecoder(cs, csn);
}
}
} catch (IllegalCharsetNameException x) {} } catch (IllegalCharsetNameException x) {}
if (sd == null) if (sd == null)
throw new UnsupportedEncodingException(csn); throw new UnsupportedEncodingException(csn);
@ -193,7 +263,7 @@ class StringCoding {
return sd.decode(ba, off, len); return sd.decode(ba, off, len);
} }
static char[] decode(Charset cs, byte[] ba, int off, int len) { static Result decode(Charset cs, byte[] ba, int off, int len) {
// (1)We never cache the "external" cs, the only benefit of creating // (1)We never cache the "external" cs, the only benefit of creating
// an additional StringDe/Encoder object to wrap it is to share the // an additional StringDe/Encoder object to wrap it is to share the
// de/encode() method. These SD/E objects are short-lived, the young-gen // de/encode() method. These SD/E objects are short-lived, the young-gen
@ -210,25 +280,39 @@ class StringCoding {
// check (... && (isTrusted || SM == null || getClassLoader0())) in trim // check (... && (isTrusted || SM == null || getClassLoader0())) in trim
// but it then can be argued that the SM is null when the operation // but it then can be argued that the SM is null when the operation
// is started... // is started...
if (cs == UTF_8) {
return StringDecoderUTF8.decode(ba, off, len, new Result());
}
CharsetDecoder cd = cs.newDecoder(); CharsetDecoder cd = cs.newDecoder();
// ascii fastpath
if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) &&
((ArrayDecoder)cd).isASCIICompatible() &&
!hasNegatives(ba, off, len))) {
if (COMPACT_STRINGS) {
return new Result().with(Arrays.copyOfRange(ba, off, off + len),
LATIN1);
} else {
return new Result().with(StringLatin1.inflate(ba, off, len), UTF16);
}
}
int en = scale(len, cd.maxCharsPerByte()); int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en]; if (len == 0) {
if (len == 0) return new Result().with();
return ca; }
boolean isTrusted = false; if (System.getSecurityManager() != null &&
if (System.getSecurityManager() != null) { cs.getClass().getClassLoader0() != null) {
if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
ba = Arrays.copyOfRange(ba, off, off + len); ba = Arrays.copyOfRange(ba, off, off + len);
off = 0; off = 0;
} }
}
cd.onMalformedInput(CodingErrorAction.REPLACE) cd.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE)
.reset(); .reset();
char[] ca = new char[en];
if (cd instanceof ArrayDecoder) { if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca); int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return safeTrim(ca, clen, cs, isTrusted); return new Result().with(ca, 0, clen);
} else { }
ByteBuffer bb = ByteBuffer.wrap(ba, off, len); ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
CharBuffer cb = CharBuffer.wrap(ca); CharBuffer cb = CharBuffer.wrap(ca);
try { try {
@ -243,11 +327,10 @@ class StringCoding {
// so this shouldn't happen // so this shouldn't happen
throw new Error(x); throw new Error(x);
} }
return safeTrim(ca, cb.position(), cs, isTrusted); return new Result().with(ca, 0, cb.position());
}
} }
static char[] decode(byte[] ba, int off, int len) { static Result decode(byte[] ba, int off, int len) {
String csn = Charset.defaultCharset().name(); String csn = Charset.defaultCharset().name();
try { try {
// use charset name decode() variant which provides caching. // use charset name decode() variant which provides caching.
@ -273,6 +356,7 @@ class StringCoding {
private static class StringEncoder { private static class StringEncoder {
private Charset cs; private Charset cs;
private CharsetEncoder ce; private CharsetEncoder ce;
private final boolean isASCIICompatible;
private final String requestedCharsetName; private final String requestedCharsetName;
private final boolean isTrusted; private final boolean isTrusted;
@ -283,6 +367,8 @@ class StringCoding {
.onMalformedInput(CodingErrorAction.REPLACE) .onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE); .onUnmappableCharacter(CodingErrorAction.REPLACE);
this.isTrusted = (cs.getClass().getClassLoader0() == null); this.isTrusted = (cs.getClass().getClassLoader0() == null);
this.isASCIICompatible = (ce instanceof ArrayEncoder) &&
((ArrayEncoder)ce).isASCIICompatible();
} }
String charsetName() { String charsetName() {
@ -295,18 +381,33 @@ class StringCoding {
return requestedCharsetName; return requestedCharsetName;
} }
byte[] encode(char[] ca, int off, int len) { byte[] encode(byte coder, byte[] val) {
// fastpath for ascii compatible
if (coder == LATIN1 && isASCIICompatible &&
!hasNegatives(val, 0, val.length)) {
return Arrays.copyOf(val, val.length);
}
int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
int en = scale(len, ce.maxBytesPerChar()); int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en]; byte[] ba = new byte[en];
if (len == 0) if (len == 0) {
return ba; return ba;
}
if (ce instanceof ArrayEncoder) { if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba); if (!isTrusted) {
return safeTrim(ba, blen, cs, isTrusted); val = Arrays.copyOf(val, val.length);
} else { }
int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
: ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
if (blen != -1) {
return safeTrim(ba, blen, isTrusted);
}
}
char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
: StringUTF16.toChars(val);
ce.reset(); ce.reset();
ByteBuffer bb = ByteBuffer.wrap(ba); ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca, off, len); CharBuffer cb = CharBuffer.wrap(ca, 0, len);
try { try {
CoderResult cr = ce.encode(cb, bb, true); CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow()) if (!cr.isUnderflow())
@ -319,12 +420,147 @@ class StringCoding {
// so this shouldn't happen // so this shouldn't happen
throw new Error(x); throw new Error(x);
} }
return safeTrim(ba, bb.position(), cs, isTrusted); return safeTrim(ba, bb.position(), isTrusted);
}
} }
} }
static byte[] encode(String charsetName, char[] ca, int off, int len) @HotSpotIntrinsicCandidate
private static int implEncodeISOArray(byte[] sa, int sp,
byte[] da, int dp, int len) {
int i = 0;
for (; i < len; i++) {
char c = StringUTF16.getChar(sa, sp++);
if (c > '\u00FF')
break;
da[dp++] = (byte)c;
}
return i;
}
static byte[] encode8859_1(byte coder, byte[] val) {
if (coder == LATIN1) {
return Arrays.copyOf(val, val.length);
}
int len = val.length >> 1;
byte[] dst = new byte[len];
int dp = 0;
int sp = 0;
int sl = len;
while (sp < sl) {
int ret = implEncodeISOArray(val, sp, dst, dp, len);
sp = sp + ret;
dp = dp + ret;
if (ret != len) {
char c = StringUTF16.getChar(val, sp++);
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
sp++;
}
dst[dp++] = '?';
len = sl - sp;
}
}
if (dp == dst.length) {
return dst;
}
return Arrays.copyOf(dst, dp);
}
static byte[] encodeASCII(byte coder, byte[] val) {
if (coder == LATIN1) {
byte[] dst = new byte[val.length];
for (int i = 0; i < val.length; i++) {
if (val[i] < 0) {
dst[i] = '?';
} else {
dst[i] = val[i];
}
}
return dst;
}
int len = val.length >> 1;
byte[] dst = new byte[len];
int dp = 0;
for (int i = 0; i < len; i++) {
char c = StringUTF16.getChar(val, i);
if (c < 0x80) {
dst[dp++] = (byte)c;
continue;
}
if (Character.isHighSurrogate(c) && i + 1 < len &&
Character.isLowSurrogate(StringUTF16.getChar(val, i + 1))) {
i++;
}
dst[dp++] = '?';
}
if (len == dp) {
return dst;
}
return Arrays.copyOf(dst, dp);
}
static byte[] encodeUTF8(byte coder, byte[] val) {
int dp = 0;
byte[] dst;
if (coder == LATIN1) {
dst = new byte[val.length << 1];
for (int sp = 0; sp < val.length; sp++) {
byte c = val[sp];
if (c < 0) {
dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
dst[dp++] = (byte)(0x80 | (c & 0x3f));
} else {
dst[dp++] = c;
}
}
} else {
int sp = 0;
int sl = val.length >> 1;
dst = new byte[sl * 3];
char c;
while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
// ascii fast loop;
dst[dp++] = (byte)c;
sp++;
}
while (sp < sl) {
c = StringUTF16.getChar(val, sp++);
if (c < 0x80) {
dst[dp++] = (byte)c;
} else if (c < 0x800) {
dst[dp++] = (byte)(0xc0 | (c >> 6));
dst[dp++] = (byte)(0x80 | (c & 0x3f));
} else if (Character.isSurrogate(c)) {
int uc = -1;
char c2;
if (Character.isHighSurrogate(c) && sp < sl &&
Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
uc = Character.toCodePoint(c, c2);
}
if (uc < 0) {
dst[dp++] = '?';
} else {
dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
dst[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
dst[dp++] = (byte)(0x80 | (uc & 0x3f));
sp++; // 2 chars
}
} else {
// 3 bytes, 16 bits
dst[dp++] = (byte)(0xe0 | ((c >> 12)));
dst[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
dst[dp++] = (byte)(0x80 | (c & 0x3f));
}
}
}
if (dp == dst.length) {
return dst;
}
return Arrays.copyOf(dst, dp);
}
static byte[] encode(String charsetName, byte coder, byte[] val)
throws UnsupportedEncodingException throws UnsupportedEncodingException
{ {
StringEncoder se = deref(encoder); StringEncoder se = deref(encoder);
@ -334,38 +570,65 @@ class StringCoding {
se = null; se = null;
try { try {
Charset cs = lookupCharset(csn); Charset cs = lookupCharset(csn);
if (cs != null) if (cs != null) {
if (cs == UTF_8) {
return encodeUTF8(coder, val);
} else if (cs == ISO_8859_1) {
return encode8859_1(coder, val);
} else if (cs == US_ASCII) {
return encodeASCII(coder, val);
}
se = new StringEncoder(cs, csn); se = new StringEncoder(cs, csn);
}
} catch (IllegalCharsetNameException x) {} } catch (IllegalCharsetNameException x) {}
if (se == null) if (se == null) {
throw new UnsupportedEncodingException (csn); throw new UnsupportedEncodingException (csn);
}
set(encoder, se); set(encoder, se);
} }
return se.encode(ca, off, len); return se.encode(coder, val);
} }
static byte[] encode(Charset cs, char[] ca, int off, int len) { static byte[] encode(Charset cs, byte coder, byte[] val) {
if (cs == UTF_8) {
return encodeUTF8(coder, val);
} else if (cs == ISO_8859_1) {
return encode8859_1(coder, val);
} else if (cs == US_ASCII) {
return encodeASCII(coder, val);
}
CharsetEncoder ce = cs.newEncoder(); CharsetEncoder ce = cs.newEncoder();
// fastpath for ascii compatible
if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
((ArrayEncoder)ce).isASCIICompatible() &&
!hasNegatives(val, 0, val.length)))) {
return Arrays.copyOf(val, val.length);
}
int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
int en = scale(len, ce.maxBytesPerChar()); int en = scale(len, ce.maxBytesPerChar());
byte[] ba = new byte[en]; byte[] ba = new byte[en];
if (len == 0) if (len == 0) {
return ba; return ba;
boolean isTrusted = false;
if (System.getSecurityManager() != null) {
if (!(isTrusted = (cs.getClass().getClassLoader0() == null))) {
ca = Arrays.copyOfRange(ca, off, off + len);
off = 0;
}
} }
boolean isTrusted = System.getSecurityManager() == null ||
cs.getClass().getClassLoader0() == null;
ce.onMalformedInput(CodingErrorAction.REPLACE) ce.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE)
.reset(); .reset();
if (ce instanceof ArrayEncoder) { if (ce instanceof ArrayEncoder) {
int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba); if (!isTrusted) {
return safeTrim(ba, blen, cs, isTrusted); val = Arrays.copyOf(val, val.length);
} else { }
int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
: ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
if (blen != -1) {
return safeTrim(ba, blen, isTrusted);
}
}
char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
: StringUTF16.toChars(val);
ByteBuffer bb = ByteBuffer.wrap(ba); ByteBuffer bb = ByteBuffer.wrap(ba);
CharBuffer cb = CharBuffer.wrap(ca, off, len); CharBuffer cb = CharBuffer.wrap(ca, 0, len);
try { try {
CoderResult cr = ce.encode(cb, bb, true); CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow()) if (!cr.isUnderflow())
@ -376,20 +639,19 @@ class StringCoding {
} catch (CharacterCodingException x) { } catch (CharacterCodingException x) {
throw new Error(x); throw new Error(x);
} }
return safeTrim(ba, bb.position(), cs, isTrusted); return safeTrim(ba, bb.position(), isTrusted);
}
} }
static byte[] encode(char[] ca, int off, int len) { static byte[] encode(byte coder, byte[] val) {
String csn = Charset.defaultCharset().name(); String csn = Charset.defaultCharset().name();
try { try {
// use charset name encode() variant which provides caching. // use charset name encode() variant which provides caching.
return encode(csn, ca, off, len); return encode(csn, coder, val);
} catch (UnsupportedEncodingException x) { } catch (UnsupportedEncodingException x) {
warnUnsupportedCharset(csn); warnUnsupportedCharset(csn);
} }
try { try {
return encode("ISO-8859-1", ca, off, len); return encode("ISO-8859-1", coder, val);
} catch (UnsupportedEncodingException x) { } catch (UnsupportedEncodingException x) {
// If this code is hit during VM initialization, MessageUtils is // If this code is hit during VM initialization, MessageUtils is
// the only way we will be able to get any kind of error message. // the only way we will be able to get any kind of error message.

View File

@ -0,0 +1,235 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.nio.charset.Charset;
import java.util.Arrays;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.COMPACT_STRINGS;
import static java.lang.Character.isSurrogate;
import static java.lang.Character.highSurrogate;
import static java.lang.Character.lowSurrogate;
import static java.lang.Character.isSupplementaryCodePoint;
import static java.lang.StringUTF16.putChar;
class StringDecoderUTF8 extends StringCoding.StringDecoder {
StringDecoderUTF8(Charset cs, String rcn) {
super(cs, rcn);
}
private static boolean isNotContinuation(int b) {
return (b & 0xc0) != 0x80;
}
private static boolean isMalformed3(int b1, int b2, int b3) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
}
private static boolean isMalformed3_2(int b1, int b2) {
return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
(b2 & 0xc0) != 0x80;
}
private static boolean isMalformed4(int b2, int b3, int b4) {
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
(b4 & 0xc0) != 0x80;
}
private static boolean isMalformed4_2(int b1, int b2) {
return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
(b2 & 0xc0) != 0x80;
}
private static boolean isMalformed4_3(int b3) {
return (b3 & 0xc0) != 0x80;
}
// for nb == 3/4
private static int malformedN(byte[] src, int sp, int nb) {
if (nb == 3) {
int b1 = src[sp++];
int b2 = src[sp++]; // no need to lookup b3
return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
isNotContinuation(b2)) ? 1 : 2;
} else if (nb == 4) { // we don't care the speed here
int b1 = src[sp++] & 0xff;
int b2 = src[sp++] & 0xff;
if (b1 > 0xf4 ||
(b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
(b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
isNotContinuation(b2))
return 1;
if (isNotContinuation(src[sp++]))
return 2;
return 3;
}
assert false;
return -1;
}
private static char repl = '\ufffd';
StringCoding.Result decode(byte[] src, int sp, int len) {
return decode(src, sp, len, result);
}
static StringCoding.Result decode(byte[] src, int sp, int len,
StringCoding.Result ret) {
int sl = sp + len;
byte[] dst = new byte[len];
int dp = 0;
if (COMPACT_STRINGS) { // Latin1 only loop
while (sp < sl) {
int b1 = src[sp];
if (b1 >= 0) {
dst[dp++] = (byte)b1;
sp++;
continue;
}
if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
sp + 1 < sl) {
int b2 = src[sp + 1];
if (!isNotContinuation(b2)) {
dst[dp++] = (byte)(((b1 << 6) ^ b2)^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0)));
sp += 2;
continue;
}
}
// anything not a latin1, including the repl
// we have to go with the utf16
break;
}
if (sp == sl) {
if (dp != dst.length) {
dst = Arrays.copyOf(dst, dp);
}
return ret.with(dst, LATIN1);
}
}
if (dp == 0) {
dst = new byte[len << 1];
} else {
byte[] buf = new byte[len << 1];
StringLatin1.inflate(dst, 0, buf, 0, dp);
dst = buf;
}
while (sp < sl) {
int b1 = src[sp++];
if (b1 >= 0) {
putChar(dst, dp++, (char) b1);
} else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
if (sp < sl) {
int b2 = src[sp++];
if (isNotContinuation(b2)) {
putChar(dst, dp++, repl);
sp--;
} else {
putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
(((byte) 0xC0 << 6) ^
((byte) 0x80 << 0))));
}
continue;
}
putChar(dst, dp++, repl);
break;
} else if ((b1 >> 4) == -2) {
if (sp + 1 < sl) {
int b2 = src[sp++];
int b3 = src[sp++];
if (isMalformed3(b1, b2, b3)) {
putChar(dst, dp++, repl);
sp -= 3;
sp += malformedN(src, sp, 3);
} else {
char c = (char)((b1 << 12) ^
(b2 << 6) ^
(b3 ^
(((byte) 0xE0 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
putChar(dst, dp++, isSurrogate(c) ? repl : c);
}
continue;
}
if (sp < sl && isMalformed3_2(b1, src[sp])) {
putChar(dst, dp++, repl);
continue;
}
putChar(dst, dp++, repl);
break;
} else if ((b1 >> 3) == -2) {
if (sp + 2 < sl) {
int b2 = src[sp++];
int b3 = src[sp++];
int b4 = src[sp++];
int uc = ((b1 << 18) ^
(b2 << 12) ^
(b3 << 6) ^
(b4 ^
(((byte) 0xF0 << 18) ^
((byte) 0x80 << 12) ^
((byte) 0x80 << 6) ^
((byte) 0x80 << 0))));
if (isMalformed4(b2, b3, b4) ||
!isSupplementaryCodePoint(uc)) { // shortest form check
putChar(dst, dp++, repl);
sp -= 4;
sp += malformedN(src, sp, 4);
} else {
putChar(dst, dp++, highSurrogate(uc));
putChar(dst, dp++, lowSurrogate(uc));
}
continue;
}
b1 &= 0xff;
if (b1 > 0xf4 ||
sp < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
putChar(dst, dp++, repl);
continue;
}
sp++;
putChar(dst, dp++, repl);
if (sp < sl && isMalformed4_3(src[sp])) {
continue;
}
break;
} else {
putChar(dst, dp++, repl);
}
}
if (dp != len) {
dst = Arrays.copyOf(dst, dp << 1);
}
return ret.with(dst, UTF16);
}
}

View File

@ -0,0 +1,600 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.Spliterator;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
import jdk.internal.HotSpotIntrinsicCandidate;
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.checkOffset;
final class StringLatin1 {
public static char charAt(byte[] value, int index) {
if (index < 0 || index >= value.length) {
throw new StringIndexOutOfBoundsException(index);
}
return (char)(value[index] & 0xff);
}
public static boolean canEncode(int cp) {
return cp >>> 8 == 0;
}
public static int length(byte[] value) {
return value.length;
}
public static int codePointAt(byte[] value, int index, int end) {
return value[index] & 0xff;
}
public static int codePointBefore(byte[] value, int index) {
return value[index - 1] & 0xff;
}
public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
return endIndex - beginIndex;
}
public static char[] toChars(byte[] value) {
char[] dst = new char[value.length];
inflate(value, 0, dst, 0, value.length);
return dst;
}
public static byte[] inflate(byte[] value, int off, int len) {
byte[] ret = StringUTF16.newBytesFor(len);
inflate(value, off, ret, 0, len);
return ret;
}
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
@HotSpotIntrinsicCandidate
public static int compareTo(byte[] value, byte[] other) {
int len1 = value.length;
int len2 = other.length;
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
if (value[k] != other[k]) {
return getChar(value, k) - getChar(other, k);
}
}
return len1 - len2;
}
@HotSpotIntrinsicCandidate
public static int compareToUTF16(byte[] value, byte[] other) {
int len1 = length(value);
int len2 = StringUTF16.length(other);
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
char c1 = getChar(value, k);
char c2 = StringUTF16.getChar(other, k);
if (c1 != c2) {
return c1 - c2;
}
}
return len1 - len2;
}
public static int hashCode(byte[] value) {
int h = 0;
for (byte v : value) {
h = 31 * h + (v & 0xff);
}
return h;
}
public static int indexOf(byte[] value, int ch, int fromIndex) {
if (!canEncode(ch)) {
return -1;
}
int max = value.length;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
byte c = (byte)ch;
for (int i = fromIndex; i < max; i++) {
if (value[i] == c) {
return i;
}
}
return -1;
}
@HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
if (value.length == 0) {
return -1;
}
return indexOf(value, value.length, str, str.length, 0);
}
@HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
byte first = str[0];
int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) {
// Look for first character.
if (value[i] != first) {
while (++i <= max && value[i] != first);
}
// Found first character, now look at the rest of value
if (i <= max) {
int j = i + 1;
int end = j + strCount - 1;
for (int k = 1; j < end && value[j] == str[k]; j++, k++);
if (j == end) {
// Found whole string.
return i;
}
}
}
return -1;
}
public static int lastIndexOf(byte[] src, int srcCount,
byte[] tgt, int tgtCount, int fromIndex) {
int min = tgtCount - 1;
int i = min + fromIndex;
int strLastIndex = tgtCount - 1;
char strLastChar = (char)(tgt[strLastIndex] & 0xff);
startSearchForLastChar:
while (true) {
while (i >= min && (src[i] & 0xff) != strLastChar) {
i--;
}
if (i < min) {
return -1;
}
int j = i - 1;
int start = j - strLastIndex;
int k = strLastIndex - 1;
while (j > start) {
if ((src[j--] & 0xff) != (tgt[k--] & 0xff)) {
i--;
continue startSearchForLastChar;
}
}
return start + 1;
}
}
public static int lastIndexOf(final byte[] value, int ch, int fromIndex) {
if (!canEncode(ch)) {
return -1;
}
int off = Math.min(fromIndex, value.length - 1);
for (; off >= 0; off--) {
if (value[off] == (byte)ch) {
return off;
}
}
return -1;
}
public static String replace(byte[] value, char oldChar, char newChar) {
if (canEncode(oldChar)) {
int len = value.length;
int i = -1;
while (++i < len) {
if (value[i] == (byte)oldChar) {
break;
}
}
if (i < len) {
if (canEncode(newChar)) {
byte buf[] = new byte[len];
for (int j = 0; j < i; j++) { // TBD arraycopy?
buf[j] = value[j];
}
while (i < len) {
byte c = value[i];
buf[i] = (c == (byte)oldChar) ? (byte)newChar : c;
i++;
}
return new String(buf, LATIN1);
} else {
byte[] buf = StringUTF16.newBytesFor(len);
// inflate from latin1 to UTF16
inflate(value, 0, buf, 0, i);
while (i < len) {
char c = (char)(value[i] & 0xff);
StringUTF16.putChar(buf, i, (c == oldChar) ? newChar : c);
i++;
}
return new String(buf, UTF16);
}
}
}
return null; // for string to return this;
}
// case insensitive
public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) {
int last = toffset + len;
while (toffset < last) {
char c1 = (char)(value[toffset++] & 0xff);
char c2 = (char)(other[ooffset++] & 0xff);
if (c1 == c2) {
continue;
}
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
return false;
}
return true;
}
public static boolean regionMatchesCI_UTF16(byte[] value, int toffset,
byte[] other, int ooffset, int len) {
int last = toffset + len;
while (toffset < last) {
char c1 = (char)(value[toffset++] & 0xff);
char c2 = StringUTF16.getChar(other, ooffset++);
if (c1 == c2) {
continue;
}
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
return false;
}
return true;
}
public static String toLowerCase(String str, byte[] value, Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int first;
final int len = value.length;
// Now check if there are any characters that need to be changed, or are surrogate
for (first = 0 ; first < len; first++) {
int cp = value[first] & 0xff;
if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR
break;
}
}
if (first == len)
return str;
String lang = locale.getLanguage();
if (lang == "tr" || lang == "az" || lang == "lt") {
return toLowerCaseEx(str, value, first, locale, true);
}
byte[] result = new byte[len];
System.arraycopy(value, 0, result, 0, first); // Just copy the first few
// lowerCase characters.
for (int i = first; i < len; i++) {
int cp = value[i] & 0xff;
cp = Character.toLowerCase(cp);
if (!canEncode(cp)) { // not a latin1 character
return toLowerCaseEx(str, value, first, locale, false);
}
result[i] = (byte)cp;
}
return new String(result, LATIN1);
}
private static String toLowerCaseEx(String str, byte[] value,
int first, Locale locale, boolean localeDependent)
{
byte[] result = StringUTF16.newBytesFor(value.length);
int resultOffset = 0;
for (int i = 0; i < first; i++) {
StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
}
for (int i = first; i < value.length; i++) {
int srcChar = value[i] & 0xff;
int lowerChar;
char[] lowerCharArray;
if (localeDependent) {
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
} else {
lowerChar = Character.toLowerCase(srcChar);
}
if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp
StringUTF16.putChar(result, resultOffset++, lowerChar);
} else {
if (lowerChar == Character.ERROR) {
lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
} else {
lowerCharArray = Character.toChars(lowerChar);
}
/* Grow result if needed */
int mapLen = lowerCharArray.length;
if (mapLen > 1) {
byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
}
for (int x = 0; x < mapLen; ++x) {
StringUTF16.putChar(result, resultOffset++, lowerCharArray[x]);
}
}
}
return StringUTF16.newString(result, 0, resultOffset);
}
public static String toUpperCase(String str, byte[] value, Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int first;
final int len = value.length;
// Now check if there are any characters that need to be changed, or are surrogate
for (first = 0 ; first < len; first++ ) {
int cp = value[first] & 0xff;
if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR
break;
}
}
if (first == len) {
return str;
}
String lang = locale.getLanguage();
if (lang == "tr" || lang == "az" || lang == "lt") {
return toUpperCaseEx(str, value, first, locale, true);
}
byte[] result = new byte[len];
System.arraycopy(value, 0, result, 0, first); // Just copy the first few
// upperCase characters.
for (int i = first; i < len; i++) {
int cp = value[i] & 0xff;
cp = Character.toUpperCaseEx(cp);
if (!canEncode(cp)) { // not a latin1 character
return toUpperCaseEx(str, value, first, locale, false);
}
result[i] = (byte)cp;
}
return new String(result, LATIN1);
}
private static String toUpperCaseEx(String str, byte[] value,
int first, Locale locale, boolean localeDependent)
{
byte[] result = StringUTF16.newBytesFor(value.length);
int resultOffset = 0;
for (int i = 0; i < first; i++) {
StringUTF16.putChar(result, resultOffset++, value[i] & 0xff);
}
for (int i = first; i < value.length; i++) {
int srcChar = value[i] & 0xff;
int upperChar;
char[] upperCharArray;
if (localeDependent) {
upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
} else {
upperChar = Character.toUpperCaseEx(srcChar);
}
if (Character.isBmpCodePoint(upperChar)) {
StringUTF16.putChar(result, resultOffset++, upperChar);
} else {
if (upperChar == Character.ERROR) {
if (localeDependent) {
upperCharArray =
ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
} else {
upperCharArray = Character.toUpperCaseCharArray(srcChar);
}
} else {
upperCharArray = Character.toChars(upperChar);
}
/* Grow result if needed */
int mapLen = upperCharArray.length;
if (mapLen > 1) {
byte[] result2 = StringUTF16.newBytesFor((result.length >> 1) + mapLen - 1);
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
}
for (int x = 0; x < mapLen; ++x) {
StringUTF16.putChar(result, resultOffset++, upperCharArray[x]);
}
}
}
return StringUTF16.newString(result, 0, resultOffset);
}
public static String trim(byte[] value) {
int len = value.length;
int st = 0;
while ((st < len) && ((value[st] & 0xff) <= ' ')) {
st++;
}
while ((st < len) && ((value[len - 1] & 0xff) <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ?
newString(value, st, len - st) : null;
}
public static void putChar(byte[] val, int index, int c) {
//assert (canEncode(c));
val[index] = (byte)(c);
}
public static char getChar(byte[] val, int index) {
return (char)(val[index] & 0xff);
}
public static byte[] toBytes(int[] val, int off, int len) {
byte[] ret = new byte[len];
for (int i = 0; i < len; i++) {
int cp = val[off++];
if (!canEncode(cp)) {
return null;
}
ret[i] = (byte)cp;
}
return ret;
}
public static byte[] toBytes(char c) {
return new byte[] { (byte)c };
}
public static String newString(byte[] val, int index, int len) {
return new String(Arrays.copyOfRange(val, index, index + len),
LATIN1);
}
public static void fillNull(byte[] val, int index, int end) {
Arrays.fill(val, index, end, (byte)0);
}
// inflatedCopy byte[] -> char[]
@HotSpotIntrinsicCandidate
private static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
dst[dstOff++] = (char)(src[srcOff++] & 0xff);
}
}
// inflatedCopy byte[] -> byte[]
@HotSpotIntrinsicCandidate
public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
StringUTF16.putChar(dst, dstOff++, src[srcOff++] & 0xff);
}
}
static class CharsSpliterator implements Spliterator.OfInt {
private final byte[] array;
private int index; // current index, modified on advance/split
private final int fence; // one past last index
private final int cs;
CharsSpliterator(byte[] array, int acs) {
this(array, 0, array.length, acs);
}
CharsSpliterator(byte[] array, int origin, int fence, int acs) {
this.array = array;
this.index = origin;
this.fence = fence;
this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
| Spliterator.SUBSIZED;
}
@Override
public OfInt trySplit() {
int lo = index, mid = (lo + fence) >>> 1;
return (lo >= mid)
? null
: new CharsSpliterator(array, lo, index = mid, cs);
}
@Override
public void forEachRemaining(IntConsumer action) {
byte[] a; int i, hi; // hoist accesses and checks from loop
if (action == null)
throw new NullPointerException();
if ((a = array).length >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept(a[i] & 0xff); } while (++i < hi);
}
}
@Override
public boolean tryAdvance(IntConsumer action) {
if (action == null)
throw new NullPointerException();
if (index >= 0 && index < fence) {
action.accept(array[index++] & 0xff);
return true;
}
return false;
}
@Override
public long estimateSize() { return (long)(fence - index); }
@Override
public int characteristics() {
return cs;
}
}
////////////////////////////////////////////////////////////////
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
checkOffset(srcEnd, val.length);
getChars(val, srcBegin, srcEnd, dst, dstBegin);
}
public static void inflateSB(byte[] val, byte[] dst, int dstOff, int count) {
checkOffset(count, val.length);
checkOffset(dstOff + count, dst.length >> 1); // dst is utf16
inflate(val, 0, dst, dstOff, count);
}
}

View File

@ -0,0 +1,971 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang;
import java.util.Arrays;
import java.util.Locale;
import java.util.Spliterator;
import java.util.function.IntConsumer;
import jdk.internal.HotSpotIntrinsicCandidate;
import static java.lang.String.UTF16;
import static java.lang.String.LATIN1;
import static java.lang.String.checkIndex;
import static java.lang.String.checkOffset;
final class StringUTF16 {
public static byte[] newBytesFor(int len) {
if (len < 0) {
throw new NegativeArraySizeException();
}
if (len > MAX_LENGTH) {
throw new OutOfMemoryError("UTF16 String size is " + len +
", should be less than " + MAX_LENGTH);
}
return new byte[len << 1];
}
@HotSpotIntrinsicCandidate
public static void putChar(byte[] val, int index, int c) {
index <<= 1;
val[index++] = (byte)(c >> HI_BYTE_SHIFT);
val[index] = (byte)(c >> LO_BYTE_SHIFT);
}
@HotSpotIntrinsicCandidate
public static char getChar(byte[] val, int index) {
index <<= 1;
return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
((val[index] & 0xff) << LO_BYTE_SHIFT));
}
public static char charAt(byte[] value, int index) {
if (index < 0 || index >= value.length >> 1) {
throw new StringIndexOutOfBoundsException(index);
}
return getChar(value, index);
}
public static int length(byte[] value) {
return value.length >> 1;
}
public static int codePointAt(byte[] value, int index, int end) {
char c1 = getChar(value, index);
if (Character.isHighSurrogate(c1) && ++index < end) {
char c2 = getChar(value, index);
if (Character.isLowSurrogate(c2)) {
return Character.toCodePoint(c1, c2);
}
}
return c1;
}
public static int codePointBefore(byte[] value, int index) {
char c2 = getChar(value, --index);
if (Character.isLowSurrogate(c2) && index > 0) {
char c1 = getChar(value, --index);
if (Character.isHighSurrogate(c1)) {
return Character.toCodePoint(c1, c2);
}
}
return c2;
}
public static int codePointCount(byte[] value, int beginIndex, int endIndex) {
int count = endIndex - beginIndex;
for (int i = beginIndex; i < endIndex; ) {
if (Character.isHighSurrogate(getChar(value, i++)) &&
i < endIndex &&
Character.isLowSurrogate(getChar(value, i))) {
count--;
i++;
}
}
return count;
}
public static char[] toChars(byte[] value) {
char[] dst = new char[value.length >> 1];
getChars(value, 0, dst.length, dst, 0);
return dst;
}
@HotSpotIntrinsicCandidate
public static byte[] toBytes(char[] value, int off, int len) {
byte[] val = newBytesFor(len);
for (int i = 0; i < len; i++) {
putChar(val, i, value[off++]);
}
return val;
}
public static byte[] compress(char[] val, int off, int len) {
byte[] ret = new byte[len];
if (compress(val, off, ret, 0, len) == len) {
return ret;
}
return null;
}
public static byte[] compress(byte[] val, int off, int len) {
byte[] ret = new byte[len];
if (compress(val, off, ret, 0, len) == len) {
return ret;
}
return null;
}
// compressedCopy char[] -> byte[]
@HotSpotIntrinsicCandidate
private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
int c = src[srcOff++];
if (c >>> 8 != 0) {
return 0;
}
dst[dstOff++] = (byte)c;
}
return len;
}
// compressedCopy byte[] -> byte[]
@HotSpotIntrinsicCandidate
public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
int c = getChar(src, srcOff++);
if (c >>> 8 != 0) {
return 0;
}
dst[dstOff++] = (byte)c;
}
return len;
}
public static byte[] toBytes(int[] val, int index, int len) {
final int end = index + len;
// Pass 1: Compute precise size of char[]
int n = len;
for (int i = index; i < end; i++) {
int cp = val[i];
if (Character.isBmpCodePoint(cp))
continue;
else if (Character.isValidCodePoint(cp))
n++;
else throw new IllegalArgumentException(Integer.toString(cp));
}
// Pass 2: Allocate and fill in <high, low> pair
byte[] buf = newBytesFor(n);
for (int i = index, j = 0; i < end; i++, j++) {
int cp = val[i];
if (Character.isBmpCodePoint(cp)) {
putChar(buf, j, cp);
} else {
putChar(buf, j++, Character.highSurrogate(cp));
putChar(buf, j, Character.lowSurrogate(cp));
}
}
return buf;
}
public static byte[] toBytes(char c) {
byte[] result = new byte[2];
putChar(result, 0, c);
return result;
}
@HotSpotIntrinsicCandidate
public static void getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin) {
for (int i = srcBegin; i < srcEnd; i++) {
dst[dstBegin++] = getChar(value, i);
}
}
/* @see java.lang.String.getBytes(int, int, byte[], int) */
public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte dst[], int dstBegin) {
srcBegin <<= 1;
srcEnd <<= 1;
for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) {
dst[dstBegin++] = value[i];
}
}
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
int len = value.length >> 1;
for (int i = 0; i < len; i++) {
if (getChar(value, i) != getChar(other, i)) {
return false;
}
}
return true;
}
return false;
}
@HotSpotIntrinsicCandidate
public static int compareTo(byte[] value, byte[] other) {
int len1 = length(value);
int len2 = length(other);
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
char c1 = getChar(value, k);
char c2 = getChar(other, k);
if (c1 != c2) {
return c1 - c2;
}
}
return len1 - len2;
}
@HotSpotIntrinsicCandidate
public static int compareToLatin1(byte[] value, byte[] other) {
int len1 = length(value);
int len2 = StringLatin1.length(other);
int lim = Math.min(len1, len2);
for (int k = 0; k < lim; k++) {
char c1 = getChar(value, k);
char c2 = StringLatin1.getChar(other, k);
if (c1 != c2) {
return c1 - c2;
}
}
return len1 - len2;
}
public static int hashCode(byte[] value) {
int h = 0;
int length = value.length >> 1;
for (int i = 0; i < length; i++) {
h = 31 * h + getChar(value, i);
}
return h;
}
public static int indexOf(byte[] value, int ch, int fromIndex) {
int max = value.length >> 1;
if (fromIndex < 0) {
fromIndex = 0;
} else if (fromIndex >= max) {
// Note: fromIndex might be near -1>>>1.
return -1;
}
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
return indexOfChar(value, ch, fromIndex, max);
} else {
return indexOfSupplementary(value, ch, fromIndex, max);
}
}
@HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
if (value.length == 0) {
return -1;
}
return indexOf(value, length(value), str, length(str), 0);
}
@HotSpotIntrinsicCandidate
public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) {
char first = getChar(str, 0);
int max = (valueCount - strCount);
for (int i = fromIndex; i <= max; i++) {
// Look for first character.
if (getChar(value, i) != first) {
while (++i <= max && getChar(value, i) != first);
}
// Found first character, now look at the rest of value
if (i <= max) {
int j = i + 1;
int end = j + strCount - 1;
for (int k = 1; j < end && getChar(value, j) == getChar(str, k); j++, k++);
if (j == end) {
// Found whole string.
return i;
}
}
}
return -1;
}
/**
* Handles indexOf Latin1 substring in UTF16 string.
*/
@HotSpotIntrinsicCandidate
public static int indexOfLatin1(byte[] value, byte[] str) {
if (str.length == 0) {
return 0;
}
if (value.length == 0) {
return -1;
}
return indexOfLatin1(value, length(value), str, str.length, 0);
}
@HotSpotIntrinsicCandidate
public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) {
char first = (char)(tgt[0] & 0xff);
int max = (srcCount - tgtCount);
for (int i = fromIndex; i <= max; i++) {
// Look for first character.
if (getChar(src, i) != first) {
while (++i <= max && getChar(src, i) != first);
}
// Found first character, now look at the rest of v2
if (i <= max) {
int j = i + 1;
int end = j + tgtCount - 1;
for (int k = 1;
j < end && getChar(src, j) == (tgt[k] & 0xff);
j++, k++);
if (j == end) {
// Found whole string.
return i;
}
}
}
return -1;
}
@HotSpotIntrinsicCandidate
private static int indexOfChar(byte[] value, int ch, int fromIndex, int max) {
for (int i = fromIndex; i < max; i++) {
if (getChar(value, i) == ch) {
return i;
}
}
return -1;
}
/**
* Handles (rare) calls of indexOf with a supplementary character.
*/
private static int indexOfSupplementary(byte[] value, int ch, int fromIndex, int max) {
if (Character.isValidCodePoint(ch)) {
final char hi = Character.highSurrogate(ch);
final char lo = Character.lowSurrogate(ch);
for (int i = fromIndex; i < max - 1; i++) {
if (getChar(value, i) == hi && getChar(value, i + 1 ) == lo) {
return i;
}
}
}
return -1;
}
public static int lastIndexOf(byte[] src, int srcCount,
byte[] tgt, int tgtCount, int fromIndex) {
int min = tgtCount - 1;
int i = min + fromIndex;
int strLastIndex = tgtCount - 1;
char strLastChar = getChar(tgt, strLastIndex);
startSearchForLastChar:
while (true) {
while (i >= min && getChar(src, i) != strLastChar) {
i--;
}
if (i < min) {
return -1;
}
int j = i - 1;
int start = j - strLastIndex;
int k = strLastIndex - 1;
while (j > start) {
if (getChar(src, j--) != getChar(tgt, k--)) {
i--;
continue startSearchForLastChar;
}
}
return start + 1;
}
}
public static int lastIndexOf(byte[] value, int ch, int fromIndex) {
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
// handle most cases here (ch is a BMP code point or a
// negative value (invalid code point))
int i = Math.min(fromIndex, (value.length >> 1) - 1);
for (; i >= 0; i--) {
if (getChar(value, i) == ch) {
return i;
}
}
return -1;
} else {
return lastIndexOfSupplementary(value, ch, fromIndex);
}
}
/**
* Handles (rare) calls of lastIndexOf with a supplementary character.
*/
private static int lastIndexOfSupplementary(final byte[] value, int ch, int fromIndex) {
if (Character.isValidCodePoint(ch)) {
char hi = Character.highSurrogate(ch);
char lo = Character.lowSurrogate(ch);
int i = Math.min(fromIndex, (value.length >> 1) - 2);
for (; i >= 0; i--) {
if (getChar(value, i) == hi && getChar(value, i + 1) == lo) {
return i;
}
}
}
return -1;
}
public static String replace(byte[] value, char oldChar, char newChar) {
int len = value.length >> 1;
int i = -1;
while (++i < len) {
if (getChar(value, i) == oldChar) {
break;
}
}
if (i < len) {
byte buf[] = new byte[value.length];
for (int j = 0; j < i; j++) {
putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
}
while (i < len) {
char c = getChar(value, i);
putChar(buf, i, c == oldChar ? newChar : c);
i++;
}
// Check if we should try to compress to latin1
if (String.COMPACT_STRINGS &&
!StringLatin1.canEncode(oldChar) &&
StringLatin1.canEncode(newChar)) {
byte[] val = compress(buf, 0, len);
if (val != null) {
return new String(val, LATIN1);
}
}
return new String(buf, UTF16);
}
return null;
}
public static boolean regionMatchesCI(byte[] value, int toffset,
byte[] other, int ooffset, int len) {
int last = toffset + len;
while (toffset < last) {
char c1 = getChar(value, toffset++);
char c2 = getChar(other, ooffset++);
if (c1 == c2) {
continue;
}
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
return false;
}
return true;
}
public static boolean regionMatchesCI_Latin1(byte[] value, int toffset,
byte[] other, int ooffset,
int len) {
int last = toffset + len;
while (toffset < last) {
char c1 = getChar(value, toffset++);
char c2 = (char)(other[ooffset++] & 0xff);
if (c1 == c2) {
continue;
}
char u1 = Character.toUpperCase(c1);
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) {
continue;
}
return false;
}
return true;
}
public static String toLowerCase(String str, byte[] value, Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int first;
boolean hasSurr = false;
final int len = value.length >> 1;
// Now check if there are any characters that need to be changed, or are surrogate
for (first = 0 ; first < len; first++) {
int cp = (int)getChar(value, first);
if (Character.isSurrogate((char)cp)) {
hasSurr = true;
break;
}
if (cp != Character.toLowerCase(cp)) { // no need to check Character.ERROR
break;
}
}
if (first == len)
return str;
byte[] result = new byte[value.length];
System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
// lowerCase characters.
String lang = locale.getLanguage();
if (lang == "tr" || lang == "az" || lang == "lt") {
return toLowerCaseEx(str, value, result, first, locale, true);
}
if (hasSurr) {
return toLowerCaseEx(str, value, result, first, locale, false);
}
int bits = 0;
for (int i = first; i < len; i++) {
int cp = (int)getChar(value, i);
if (cp == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
Character.isSurrogate((char)cp)) {
return toLowerCaseEx(str, value, result, i, locale, false);
}
if (cp == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
return toLowerCaseEx(str, value, result, i, locale, true);
}
cp = Character.toLowerCase(cp);
if (!Character.isBmpCodePoint(cp)) {
return toLowerCaseEx(str, value, result, i, locale, false);
}
bits |= cp;
putChar(result, i, cp);
}
if (bits >>> 8 != 0) {
return new String(result, UTF16);
} else {
return newString(result, 0, len);
}
}
private static String toLowerCaseEx(String str, byte[] value,
byte[] result, int first, Locale locale,
boolean localeDependent) {
int resultOffset = first;
int length = value.length >> 1;
int srcCount;
for (int i = first; i < length; i += srcCount) {
int srcChar = getChar(value, i);
int lowerChar;
char[] lowerCharArray;
srcCount = 1;
if (Character.isSurrogate((char)srcChar)) {
srcChar = codePointAt(value, i, length);
srcCount = Character.charCount(srcChar);
}
if (localeDependent ||
srcChar == '\u03A3' || // GREEK CAPITAL LETTER SIGMA
srcChar == '\u0130') { // LATIN CAPITAL LETTER I WITH DOT ABOVE
lowerChar = ConditionalSpecialCasing.toLowerCaseEx(str, i, locale);
} else {
lowerChar = Character.toLowerCase(srcChar);
}
if (Character.isBmpCodePoint(lowerChar)) { // Character.ERROR is not a bmp
putChar(result, resultOffset++, lowerChar);
} else {
if (lowerChar == Character.ERROR) {
lowerCharArray = ConditionalSpecialCasing.toLowerCaseCharArray(str, i, locale);
} else {
lowerCharArray = Character.toChars(lowerChar);
}
/* Grow result if needed */
int mapLen = lowerCharArray.length;
if (mapLen > srcCount) {
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
}
for (int x = 0; x < mapLen; ++x) {
putChar(result, resultOffset++, lowerCharArray[x]);
}
}
}
return newString(result, 0, resultOffset);
}
public static String toUpperCase(String str, byte[] value, Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int first;
boolean hasSurr = false;
final int len = value.length >> 1;
// Now check if there are any characters that need to be changed, or are surrogate
for (first = 0 ; first < len; first++) {
int cp = (int)getChar(value, first);
if (Character.isSurrogate((char)cp)) {
hasSurr = true;
break;
}
if (cp != Character.toUpperCaseEx(cp)) { // no need to check Character.ERROR
break;
}
}
if (first == len) {
return str;
}
byte[] result = new byte[value.length];
System.arraycopy(value, 0, result, 0, first << 1); // Just copy the first few
// upperCase characters.
String lang = locale.getLanguage();
if (lang == "tr" || lang == "az" || lang == "lt") {
return toUpperCaseEx(str, value, result, first, locale, true);
}
if (hasSurr) {
return toUpperCaseEx(str, value, result, first, locale, false);
}
int bits = 0;
for (int i = first; i < len; i++) {
int cp = (int)getChar(value, i);
if (Character.isSurrogate((char)cp)) {
return toUpperCaseEx(str, value, result, i, locale, false);
}
cp = Character.toUpperCaseEx(cp);
if (!Character.isBmpCodePoint(cp)) { // Character.ERROR is not bmp
return toUpperCaseEx(str, value, result, i, locale, false);
}
bits |= cp;
putChar(result, i, cp);
}
if (bits >>> 8 != 0) {
return new String(result, UTF16);
} else {
return newString(result, 0, len);
}
}
private static String toUpperCaseEx(String str, byte[] value,
byte[] result, int first,
Locale locale, boolean localeDependent)
{
int resultOffset = first;
int length = value.length >> 1;
int srcCount;
for (int i = first; i < length; i += srcCount) {
int srcChar = getChar(value, i);
int upperChar;
char[] upperCharArray;
srcCount = 1;
if (Character.isSurrogate((char)srcChar)) {
srcChar = codePointAt(value, i, length);
srcCount = Character.charCount(srcChar);
}
if (localeDependent) {
upperChar = ConditionalSpecialCasing.toUpperCaseEx(str, i, locale);
} else {
upperChar = Character.toUpperCaseEx(srcChar);
}
if (Character.isBmpCodePoint(upperChar)) {
putChar(result, resultOffset++, upperChar);
} else {
if (upperChar == Character.ERROR) {
if (localeDependent) {
upperCharArray =
ConditionalSpecialCasing.toUpperCaseCharArray(str, i, locale);
} else {
upperCharArray = Character.toUpperCaseCharArray(srcChar);
}
} else {
upperCharArray = Character.toChars(upperChar);
}
/* Grow result if needed */
int mapLen = upperCharArray.length;
if (mapLen > srcCount) {
byte[] result2 = newBytesFor((result.length >> 1) + mapLen - srcCount);
System.arraycopy(result, 0, result2, 0, resultOffset << 1);
result = result2;
}
for (int x = 0; x < mapLen; ++x) {
putChar(result, resultOffset++, upperCharArray[x]);
}
}
}
return newString(result, 0, resultOffset);
}
public static String trim(byte[] value) {
int length = value.length >> 1;
int len = length;
int st = 0;
while (st < len && getChar(value, st) <= ' ') {
st++;
}
while (st < len && getChar(value, len - 1) <= ' ') {
len--;
}
return ((st > 0) || (len < length )) ?
new String(Arrays.copyOfRange(value, st << 1, len << 1), UTF16) :
null;
}
public static void putChars(byte[] val, int index, char[] str, int off, int end) {
while (off < end) {
putChar(val, index++, str[off++]);
}
}
public static String newString(byte[] val, int index, int len) {
if (String.COMPACT_STRINGS) {
byte[] buf = compress(val, index, len);
if (buf != null) {
return new String(buf, LATIN1);
}
}
int last = index + len;
return new String(Arrays.copyOfRange(val, index << 1, last << 1), UTF16);
}
public static void fillNull(byte[] val, int index, int end) {
Arrays.fill(val, index << 1, end << 1, (byte)0);
}
static class CharsSpliterator implements Spliterator.OfInt {
private final byte[] array;
private int index; // current index, modified on advance/split
private final int fence; // one past last index
private final int cs;
CharsSpliterator(byte[] array, int acs) {
this(array, 0, array.length >> 1, acs);
}
CharsSpliterator(byte[] array, int origin, int fence, int acs) {
this.array = array;
this.index = origin;
this.fence = fence;
this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
| Spliterator.SUBSIZED;
}
@Override
public OfInt trySplit() {
int lo = index, mid = (lo + fence) >>> 1;
return (lo >= mid)
? null
: new CharsSpliterator(array, lo, index = mid, cs);
}
@Override
public void forEachRemaining(IntConsumer action) {
byte[] a; int i, hi; // hoist accesses and checks from loop
if (action == null)
throw new NullPointerException();
if (((a = array).length >> 1) >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do { action.accept(getChar(a, i)); } while (++i < hi);
}
}
@Override
public boolean tryAdvance(IntConsumer action) {
if (action == null)
throw new NullPointerException();
if (index >= 0 && index < fence) {
action.accept(getChar(array, index++));
return true;
}
return false;
}
@Override
public long estimateSize() { return (long)(fence - index); }
@Override
public int characteristics() {
return cs;
}
}
static class CodePointsSpliterator implements Spliterator.OfInt {
private final byte[] array;
private int index; // current index, modified on advance/split
private final int fence; // one past last index
private final int cs;
CodePointsSpliterator(byte[] array, int acs) {
this(array, 0, array.length >> 1, acs);
}
CodePointsSpliterator(byte[] array, int origin, int fence, int acs) {
this.array = array;
this.index = origin;
this.fence = fence;
this.cs = acs | Spliterator.ORDERED;
}
@Override
public OfInt trySplit() {
int lo = index, mid = (lo + fence) >>> 1;
if (lo >= mid)
return null;
int midOneLess;
// If the mid-point intersects a surrogate pair
if (Character.isLowSurrogate(getChar(array, mid)) &&
Character.isHighSurrogate(getChar(array, midOneLess = (mid -1)))) {
// If there is only one pair it cannot be split
if (lo >= midOneLess)
return null;
// Shift the mid-point to align with the surrogate pair
return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
}
return new CodePointsSpliterator(array, lo, index = mid, cs);
}
@Override
public void forEachRemaining(IntConsumer action) {
byte[] a; int i, hi; // hoist accesses and checks from loop
if (action == null)
throw new NullPointerException();
if (((a = array).length >> 1) >= (hi = fence) &&
(i = index) >= 0 && i < (index = hi)) {
do {
i = advance(a, i, hi, action);
} while (i < hi);
}
}
@Override
public boolean tryAdvance(IntConsumer action) {
if (action == null)
throw new NullPointerException();
if (index >= 0 && index < fence) {
index = advance(array, index, fence, action);
return true;
}
return false;
}
// Advance one code point from the index, i, and return the next
// index to advance from
private static int advance(byte[] a, int i, int hi, IntConsumer action) {
char c1 = getChar(a, i++);
int cp = c1;
if (Character.isHighSurrogate(c1) && i < hi) {
char c2 = getChar(a, i);
if (Character.isLowSurrogate(c2)) {
i++;
cp = Character.toCodePoint(c1, c2);
}
}
action.accept(cp);
return i;
}
@Override
public long estimateSize() { return (long)(fence - index); }
@Override
public int characteristics() {
return cs;
}
}
////////////////////////////////////////////////////////////////
public static void getCharsSB(byte[] val, int srcBegin, int srcEnd, char dst[], int dstBegin) {
checkOffset(srcEnd, val.length >> 1);
getChars(val, srcBegin, srcEnd, dst, dstBegin);
}
public static void putCharSB(byte[] val, int index, int c) {
checkIndex(index, val.length >> 1);
putChar(val, index, c);
}
public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) {
checkOffset(index + end - off, val.length >> 1);
putChars(val, index, ca, off, end);
}
public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) {
checkOffset(index + end - off, val.length >> 1);
for (int i = off; i < end; i++) {
putChar(val, index++, s.charAt(i));
}
}
public static int codePointAtSB(byte[] val, int index, int end) {
checkOffset(end, val.length >> 1);
return codePointAt(val, index, end);
}
public static int codePointBeforeSB(byte[] val, int index) {
checkOffset(index, val.length >> 1);
return codePointBefore(val, index);
}
public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) {
checkOffset(endIndex, val.length >> 1);
return codePointCount(val, beginIndex, endIndex);
}
public static String newStringSB(byte[] val, int index, int len) {
checkOffset(index + len, val.length >> 1);
return newString(val, index, len);
}
////////////////////////////////////////////////////////////////
private static native boolean isBigEndian();
static final int HI_BYTE_SHIFT;
static final int LO_BYTE_SHIFT;
static {
if (isBigEndian()) {
HI_BYTE_SHIFT = 8;
LO_BYTE_SHIFT = 0;
} else {
HI_BYTE_SHIFT = 0;
LO_BYTE_SHIFT = 8;
}
}
static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
}

View File

@ -34,14 +34,16 @@ import java.lang.invoke.LambdaForm.NamedFunction;
import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.function.Function;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.org.objectweb.asm.FieldVisitor;
import sun.invoke.util.ValueConversions; import sun.invoke.util.ValueConversions;
import sun.invoke.util.Wrapper; import sun.invoke.util.Wrapper;
import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Type;
/** /**
* The flavor of method handle which emulates an invoke instruction * The flavor of method handle which emulates an invoke instruction
@ -217,7 +219,7 @@ import jdk.internal.org.objectweb.asm.Type;
/*non-public*/ int fieldCount() { /*non-public*/ int fieldCount() {
return 1; return 1;
} }
/*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class); /*non-public*/ static final SpeciesData SPECIES_DATA = new SpeciesData("L", Species_L.class);
/*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) { /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
return new Species_L(mt, lf, argL0); return new Species_L(mt, lf, argL0);
} }
@ -335,7 +337,7 @@ import jdk.internal.org.objectweb.asm.Type;
static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class); static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
this.typeChars = types; this.typeChars = types;
this.typeCodes = basicTypes(types); this.typeCodes = basicTypes(types);
this.clazz = clazz; this.clazz = clazz;
@ -355,26 +357,14 @@ import jdk.internal.org.objectweb.asm.Type;
assert(!INIT_DONE); assert(!INIT_DONE);
if (constructor() == null) { if (constructor() == null) {
String types = typeChars; String types = typeChars;
CACHE.put(types, this);
Factory.makeCtors(clazz, types, this.constructor); Factory.makeCtors(clazz, types, this.constructor);
Factory.makeGetters(clazz, types, this.getters); Factory.makeGetters(clazz, types, this.getters);
Factory.makeNominalGetters(types, this.nominalGetters, this.getters); Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
} }
} }
private SpeciesData(String typeChars) { private static final ConcurrentMap<String, SpeciesData> CACHE = new ConcurrentHashMap<>();
// Placeholder only.
this.typeChars = typeChars;
this.typeCodes = basicTypes(typeChars);
this.clazz = null;
this.constructor = null;
this.getters = null;
this.nominalGetters = null;
this.extensions = null;
}
private boolean isPlaceholder() { return clazz == null; }
private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
static { CACHE.put("", EMPTY); } // make bootstrap predictable
private static final boolean INIT_DONE; // set after <clinit> finishes... private static final boolean INIT_DONE; // set after <clinit> finishes...
SpeciesData extendWith(byte type) { SpeciesData extendWith(byte type) {
@ -390,62 +380,52 @@ import jdk.internal.org.objectweb.asm.Type;
} }
private static SpeciesData get(String types) { private static SpeciesData get(String types) {
// Acquire cache lock for query. return CACHE.computeIfAbsent(types, new Function<String, SpeciesData>() {
SpeciesData d = lookupCache(types); @Override
if (!d.isPlaceholder()) public SpeciesData apply(String types) {
return d; Class<? extends BoundMethodHandle> bmhcl = Factory.getConcreteBMHClass(types);
synchronized (d) { // SpeciesData instantiation may throw VirtualMachineError because of
// Use synch. on the placeholder to prevent multiple instantiation of one species. // code cache overflow...
// Creating this class forces a recursive call to getForClass. SpeciesData speciesData = new SpeciesData(types, bmhcl);
if (lookupCache(types).isPlaceholder()) // CHM.computeIfAbsent ensures only one SpeciesData will be set
Factory.generateConcreteBMHClass(types); // successfully on the concrete BMH class if ever
Factory.setSpeciesDataToConcreteBMHClass(bmhcl, speciesData);
// the concrete BMH class is published via SpeciesData instance
// returned here only after it's SPECIES_DATA field is set
return speciesData;
} }
// Reacquire cache lock. });
d = lookupCache(types);
// Class loading must have upgraded the cache.
assert(d != null && !d.isPlaceholder());
return d;
}
static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
// clazz is a new class which is initializing its SPECIES_DATA field
return updateCache(types, new SpeciesData(types, clazz));
}
private static synchronized SpeciesData lookupCache(String types) {
SpeciesData d = CACHE.get(types);
if (d != null) return d;
d = new SpeciesData(types);
assert(d.isPlaceholder());
CACHE.put(types, d);
return d;
}
private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
SpeciesData d2;
assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
assert(!d.isPlaceholder());
CACHE.put(types, d);
return d;
} }
static { /**
// pre-fill the BMH speciesdata cache with BMH's inner classes * This is to be called when assertions are enabled. It checks whether SpeciesData for all of the statically
final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class; * defined species subclasses of BoundMethodHandle has been added to the SpeciesData cache. See below in the
* static initializer for
*/
static boolean speciesDataCachePopulated() {
Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
try { try {
for (Class<?> c : rootCls.getDeclaredClasses()) { for (Class<?> c : rootCls.getDeclaredClasses()) {
if (rootCls.isAssignableFrom(c)) { if (rootCls.isAssignableFrom(c)) {
final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class); final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh); SpeciesData d = Factory.getSpeciesDataFromConcreteBMHClass(cbmh);
assert(d != null) : cbmh.getName(); assert(d != null) : cbmh.getName();
assert(d.clazz == cbmh); assert(d.clazz == cbmh);
assert(d == lookupCache(d.typeChars)); assert(CACHE.get(d.typeChars) == d);
} }
} }
} catch (Throwable e) { } catch (Throwable e) {
throw newInternalError(e); throw newInternalError(e);
} }
return true;
for (SpeciesData d : CACHE.values()) {
d.initForBootstrap();
} }
static {
// Pre-fill the BMH species-data cache with EMPTY and all BMH's inner subclasses.
EMPTY.initForBootstrap();
Species_L.SPECIES_DATA.initForBootstrap();
// check that all static SpeciesData instances have been initialized
assert speciesDataCachePopulated();
// Note: Do not simplify this, because INIT_DONE must not be // Note: Do not simplify this, because INIT_DONE must not be
// a compile-time constant during bootstrapping. // a compile-time constant during bootstrapping.
INIT_DONE = Boolean.TRUE; INIT_DONE = Boolean.TRUE;
@ -479,6 +459,7 @@ import jdk.internal.org.objectweb.asm.Type;
static final String BMH_SIG = "L"+BMH+";"; static final String BMH_SIG = "L"+BMH+";";
static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData"; static final String SPECIES_DATA = "java/lang/invoke/BoundMethodHandle$SpeciesData";
static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";"; static final String SPECIES_DATA_SIG = "L"+SPECIES_DATA+";";
static final String STABLE_SIG = "Ljava/lang/invoke/Stable;";
static final String SPECIES_PREFIX_NAME = "Species_"; static final String SPECIES_PREFIX_NAME = "Species_";
static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME; static final String SPECIES_PREFIX_PATH = BMH + "$" + SPECIES_PREFIX_NAME;
@ -493,6 +474,26 @@ import jdk.internal.org.objectweb.asm.Type;
static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" }; static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
static final ConcurrentMap<String, Class<? extends BoundMethodHandle>> CLASS_CACHE = new ConcurrentHashMap<>();
/**
* Get a concrete subclass of BMH for a given combination of bound types.
*
* @param types the type signature, wherein reference types are erased to 'L'
* @return the concrete BMH class
*/
static Class<? extends BoundMethodHandle> getConcreteBMHClass(String types) {
// CHM.computeIfAbsent ensures generateConcreteBMHClass is called
// only once per key.
return CLASS_CACHE.computeIfAbsent(
types, new Function<String, Class<? extends BoundMethodHandle>>() {
@Override
public Class<? extends BoundMethodHandle> apply(String types) {
return generateConcreteBMHClass(types);
}
});
}
/** /**
* Generate a concrete subclass of BMH for a given combination of bound types. * Generate a concrete subclass of BMH for a given combination of bound types.
* *
@ -529,7 +530,7 @@ import jdk.internal.org.objectweb.asm.Type;
* } * }
* final SpeciesData speciesData() { return SPECIES_DATA; } * final SpeciesData speciesData() { return SPECIES_DATA; }
* final int fieldCount() { return 3; } * final int fieldCount() { return 3; }
* static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class); * &#64;Stable static SpeciesData SPECIES_DATA; // injected afterwards
* static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) { * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
* return new Species_LLI(mt, lf, argL0, argL1, argI2); * return new Species_LLI(mt, lf, argL0, argL1, argI2);
* } * }
@ -568,7 +569,9 @@ import jdk.internal.org.objectweb.asm.Type;
cw.visitSource(sourceFile, null); cw.visitSource(sourceFile, null);
// emit static types and SPECIES_DATA fields // emit static types and SPECIES_DATA fields
cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd(); FieldVisitor fw = cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null);
fw.visitAnnotation(STABLE_SIG, true);
fw.visitEnd();
// emit bound argument fields // emit bound argument fields
for (int i = 0; i < types.length(); ++i) { for (int i = 0; i < types.length(); ++i) {
@ -694,17 +697,6 @@ import jdk.internal.org.objectweb.asm.Type;
mv.visitEnd(); mv.visitEnd();
} }
// emit class initializer
mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
mv.visitCode();
mv.visitLdcInsn(types);
mv.visitLdcInsn(Type.getObjectType(className));
mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false);
mv.visitFieldInsn(PUTSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
cw.visitEnd(); cw.visitEnd();
// load class // load class
@ -715,7 +707,6 @@ import jdk.internal.org.objectweb.asm.Type;
UNSAFE.defineClass(className, classFile, 0, classFile.length, UNSAFE.defineClass(className, classFile, 0, classFile.length,
BoundMethodHandle.class.getClassLoader(), null) BoundMethodHandle.class.getClassLoader(), null)
.asSubclass(BoundMethodHandle.class); .asSubclass(BoundMethodHandle.class);
UNSAFE.ensureClassInitialized(bmhClass);
return bmhClass; return bmhClass;
} }
@ -785,7 +776,7 @@ import jdk.internal.org.objectweb.asm.Type;
// Auxiliary methods. // Auxiliary methods.
// //
static SpeciesData speciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) { static SpeciesData getSpeciesDataFromConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh) {
try { try {
Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA"); Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
return (SpeciesData) F_SPECIES_DATA.get(null); return (SpeciesData) F_SPECIES_DATA.get(null);
@ -794,6 +785,16 @@ import jdk.internal.org.objectweb.asm.Type;
} }
} }
static void setSpeciesDataToConcreteBMHClass(Class<? extends BoundMethodHandle> cbmh, SpeciesData speciesData) {
try {
Field F_SPECIES_DATA = cbmh.getDeclaredField("SPECIES_DATA");
assert F_SPECIES_DATA.getDeclaredAnnotation(Stable.class) != null;
F_SPECIES_DATA.set(null, speciesData);
} catch (ReflectiveOperationException ex) {
throw newInternalError(ex);
}
}
/** /**
* Field names in concrete BMHs adhere to this pattern: * Field names in concrete BMHs adhere to this pattern:
* arg + type + index * arg + type + index

View File

@ -25,7 +25,7 @@
package java.lang.invoke; package java.lang.invoke;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import sun.invoke.util.VerifyAccess; import sun.invoke.util.VerifyAccess;

View File

@ -27,7 +27,7 @@ package java.lang.invoke;
import jdk.internal.org.objectweb.asm.*; import jdk.internal.org.objectweb.asm.*;
import sun.invoke.util.BytecodeDescriptor; import sun.invoke.util.BytecodeDescriptor;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import java.io.FilePermission; import java.io.FilePermission;

View File

@ -775,7 +775,7 @@ class InvokerBytecodeGenerator {
// Sample classes from each package we are willing to bind to statically: // Sample classes from each package we are willing to bind to statically:
java.lang.Object.class, java.lang.Object.class,
java.util.Arrays.class, java.util.Arrays.class,
sun.misc.Unsafe.class jdk.internal.misc.Unsafe.class
//MethodHandle.class already covered //MethodHandle.class already covered
}; };

View File

@ -694,8 +694,11 @@ import java.util.Objects;
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(clazz, getReferenceKind(), name, getType()); // Avoid autoboxing getReferenceKind(), since this is used early and will force
// early initialization of Byte$ByteCache
return Objects.hash(clazz, new Byte(getReferenceKind()), name, getType());
} }
@Override @Override
public boolean equals(Object that) { public boolean equals(Object that) {
return (that instanceof MemberName && this.equals((MemberName)that)); return (that instanceof MemberName && this.equals((MemberName)that));

View File

@ -50,7 +50,7 @@ class MethodHandleNatives {
static native int getMembers(Class<?> defc, String matchName, String matchSig, static native int getMembers(Class<?> defc, String matchName, String matchSig,
int matchFlags, Class<?> caller, int skip, MemberName[] results); int matchFlags, Class<?> caller, int skip, MemberName[] results);
/// Field layout queries parallel to sun.misc.Unsafe: /// Field layout queries parallel to jdk.internal.misc.Unsafe:
static native long objectFieldOffset(MemberName self); // e.g., returns vmindex static native long objectFieldOffset(MemberName self); // e.g., returns vmindex
static native long staticFieldOffset(MemberName self); // e.g., returns vmindex static native long staticFieldOffset(MemberName self); // e.g., returns vmindex
static native Object staticFieldBase(MemberName self); // e.g., returns clazz static native Object staticFieldBase(MemberName self); // e.g., returns clazz

View File

@ -27,7 +27,7 @@ package java.lang.invoke;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
* This class consists exclusively of static names internal to the * This class consists exclusively of static names internal to the

View File

@ -3726,12 +3726,12 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
} }
private static class UnsafeHolder { private static class UnsafeHolder {
private static final sun.misc.Unsafe unsafe; private static final jdk.internal.misc.Unsafe unsafe;
private static final long intCompactOffset; private static final long intCompactOffset;
private static final long intValOffset; private static final long intValOffset;
static { static {
try { try {
unsafe = sun.misc.Unsafe.getUnsafe(); unsafe = jdk.internal.misc.Unsafe.getUnsafe();
intCompactOffset = unsafe.objectFieldOffset intCompactOffset = unsafe.objectFieldOffset
(BigDecimal.class.getDeclaredField("intCompact")); (BigDecimal.class.getDeclaredField("intCompact"));
intValOffset = unsafe.objectFieldOffset intValOffset = unsafe.objectFieldOffset

View File

@ -4526,12 +4526,12 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// Support for resetting final fields while deserializing // Support for resetting final fields while deserializing
private static class UnsafeHolder { private static class UnsafeHolder {
private static final sun.misc.Unsafe unsafe; private static final jdk.internal.misc.Unsafe unsafe;
private static final long signumOffset; private static final long signumOffset;
private static final long magOffset; private static final long magOffset;
static { static {
try { try {
unsafe = sun.misc.Unsafe.getUnsafe(); unsafe = jdk.internal.misc.Unsafe.getUnsafe();
signumOffset = unsafe.objectFieldOffset signumOffset = unsafe.objectFieldOffset
(BigInteger.class.getDeclaredField("signum")); (BigInteger.class.getDeclaredField("signum"));
magOffset = unsafe.objectFieldOffset magOffset = unsafe.objectFieldOffset

View File

@ -576,11 +576,11 @@ class Inet6Address extends InetAddress {
}; };
private static final long FIELDS_OFFSET; private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE; private static final jdk.internal.misc.Unsafe UNSAFE;
static { static {
try { try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset( FIELDS_OFFSET = unsafe.objectFieldOffset(
Inet6Address.class.getDeclaredField("holder6")); Inet6Address.class.getDeclaredField("holder6"));
UNSAFE = unsafe; UNSAFE = unsafe;

View File

@ -29,6 +29,7 @@ import java.util.NavigableSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -733,7 +734,7 @@ class InetAddress implements java.io.Serializable {
*/ */
public String toString() { public String toString() {
String hostName = holder().getHostName(); String hostName = holder().getHostName();
return ((hostName != null) ? hostName : "") return Objects.toString(hostName, "")
+ "/" + getHostAddress(); + "/" + getHostAddress();
} }
@ -1493,11 +1494,11 @@ class InetAddress implements java.io.Serializable {
} }
private static final long FIELDS_OFFSET; private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE; private static final jdk.internal.misc.Unsafe UNSAFE;
static { static {
try { try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset( FIELDS_OFFSET = unsafe.objectFieldOffset(
InetAddress.class.getDeclaredField("holder") InetAddress.class.getDeclaredField("holder")
); );

View File

@ -303,10 +303,10 @@ public class InetSocketAddress
} }
private static final long FIELDS_OFFSET; private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE; private static final jdk.internal.misc.Unsafe UNSAFE;
static { static {
try { try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); jdk.internal.misc.Unsafe unsafe = jdk.internal.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset( FIELDS_OFFSET = unsafe.objectFieldOffset(
InetSocketAddress.class.getDeclaredField("holder")); InetSocketAddress.class.getDeclaredField("holder"));
UNSAFE = unsafe; UNSAFE = unsafe;

View File

@ -61,21 +61,21 @@ public interface SocketOptions {
* If the requested option is binary, it can be set using this method by * If the requested option is binary, it can be set using this method by
* a java.lang.Boolean: * a java.lang.Boolean:
* <BR><PRE> * <BR><PRE>
* s.setOption(TCP_NODELAY, new Boolean(true)); * s.setOption(TCP_NODELAY, Boolean.TRUE);
* // OK - enables TCP_NODELAY, a binary option * // OK - enables TCP_NODELAY, a binary option
* </PRE> * </PRE>
* <BR> * <BR>
* Any option can be disabled using this method with a Boolean(false): * Any option can be disabled using this method with a Boolean.FALSE:
* <BR><PRE> * <BR><PRE>
* s.setOption(TCP_NODELAY, new Boolean(false)); * s.setOption(TCP_NODELAY, Boolean.FALSE);
* // OK - disables TCP_NODELAY * // OK - disables TCP_NODELAY
* s.setOption(SO_LINGER, new Boolean(false)); * s.setOption(SO_LINGER, Boolean.FALSE);
* // OK - disables SO_LINGER * // OK - disables SO_LINGER
* </PRE> * </PRE>
* <BR> * <BR>
* For an option that has a notion of on and off, and requires * For an option that has a notion of on and off, and requires
* a non-boolean parameter, setting its value to anything other than * a non-boolean parameter, setting its value to anything other than
* <I>Boolean(false)</I> implicitly enables it. * <I>Boolean.FALSE</I> implicitly enables it.
* <BR> * <BR>
* Throws SocketException if the option is unrecognized, * Throws SocketException if the option is unrecognized,
* the socket is closed, or some low-level error occurred * the socket is closed, or some low-level error occurred
@ -91,8 +91,8 @@ public interface SocketOptions {
/** /**
* Fetch the value of an option. * Fetch the value of an option.
* Binary options will return java.lang.Boolean(true) * Binary options will return java.lang.Boolean.TRUE
* if enabled, java.lang.Boolean(false) if disabled, e.g.: * if enabled, java.lang.Boolean.FALSE if disabled, e.g.:
* <BR><PRE> * <BR><PRE>
* SocketImpl s; * SocketImpl s;
* ... * ...
@ -105,13 +105,13 @@ public interface SocketOptions {
* <P> * <P>
* For options that take a particular type as a parameter, * For options that take a particular type as a parameter,
* getOption(int) will return the parameter's value, else * getOption(int) will return the parameter's value, else
* it will return java.lang.Boolean(false): * it will return java.lang.Boolean.FALSE:
* <PRE> * <PRE>
* Object o = s.getOption(SO_LINGER); * Object o = s.getOption(SO_LINGER);
* if (o instanceof Integer) { * if (o instanceof Integer) {
* System.out.print("Linger time is " + ((Integer)o).intValue()); * System.out.print("Linger time is " + ((Integer)o).intValue());
* } else { * } else {
* // the true type of o is java.lang.Boolean(false); * // the true type of o is java.lang.Boolean.FALSE;
* } * }
* </PRE> * </PRE>
* *

View File

@ -32,6 +32,7 @@ import java.security.PrivilegedAction;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.Iterator;
import java.util.Objects;
import java.util.ServiceConfigurationError; import java.util.ServiceConfigurationError;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -1250,7 +1251,7 @@ public abstract class URLConnection {
if (handler != null) { if (handler != null) {
ContentHandler h = handlers.putIfAbsent(contentType, handler); ContentHandler h = handlers.putIfAbsent(contentType, handler);
return h != null ? h : handler; return Objects.requireNonNullElse(h, handler);
} }
try { try {
@ -1263,7 +1264,7 @@ public abstract class URLConnection {
assert handler != null; assert handler != null;
ContentHandler h = handlers.putIfAbsent(contentType, handler); ContentHandler h = handlers.putIfAbsent(contentType, handler);
return h != null ? h : handler; return Objects.requireNonNullElse(h, handler);
} }
/* /*

View File

@ -32,7 +32,7 @@ import java.util.concurrent.atomic.LongAdder;
import jdk.internal.misc.JavaNioAccess; import jdk.internal.misc.JavaNioAccess;
import jdk.internal.misc.JavaLangRefAccess; import jdk.internal.misc.JavaLangRefAccess;
import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.SharedSecrets;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import sun.misc.VM; import sun.misc.VM;
/** /**

View File

@ -29,7 +29,7 @@ package java.nio;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import sun.misc.Cleaner; import sun.misc.Cleaner;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
import sun.misc.VM; import sun.misc.VM;
import sun.nio.ch.DirectBuffer; import sun.nio.ch.DirectBuffer;

View File

@ -27,7 +27,7 @@
package java.nio; package java.nio;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
#if[rw] #if[rw]
@ -477,7 +477,7 @@ class Heap$Type$Buffer$RW$
#if[rw] #if[rw]
public float getFloat() { public float getFloat() {
int x = unsafe.getIntUnaligned(hb, byteOffset(nextPutIndex(4)), bigEndian); int x = unsafe.getIntUnaligned(hb, byteOffset(nextGetIndex(4)), bigEndian);
return Float.intBitsToFloat(x); return Float.intBitsToFloat(x);
} }

View File

@ -26,7 +26,7 @@
package java.nio; package java.nio;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**

View File

@ -37,6 +37,7 @@ import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.ServiceConfigurationError; import java.util.ServiceConfigurationError;
@ -625,6 +626,7 @@ public abstract class Charset
private final String name; // tickles a bug in oldjavac private final String name; // tickles a bug in oldjavac
private final String[] aliases; // tickles a bug in oldjavac private final String[] aliases; // tickles a bug in oldjavac
private final String[] zeroAliases = new String[0];
private Set<String> aliasSet = null; private Set<String> aliasSet = null;
/** /**
@ -642,7 +644,7 @@ public abstract class Charset
*/ */
protected Charset(String canonicalName, String[] aliases) { protected Charset(String canonicalName, String[] aliases) {
checkName(canonicalName); checkName(canonicalName);
String[] as = (aliases == null) ? new String[0] : aliases; String[] as = Objects.requireNonNullElse(aliases, zeroAliases);
for (int i = 0; i < as.length; i++) for (int i = 0; i < as.length; i++)
checkName(as[i]); checkName(as[i]);
this.name = canonicalName; this.name = canonicalName;

View File

@ -419,7 +419,7 @@ public class SecureRandom extends java.util.Random {
* @since 1.5 * @since 1.5
*/ */
public String getAlgorithm() { public String getAlgorithm() {
return (algorithm != null) ? algorithm : "unknown"; return Objects.toString(algorithm, "unknown");
} }
/** /**

View File

@ -310,8 +310,7 @@ public abstract class ZoneId implements Serializable {
public static ZoneId of(String zoneId, Map<String, String> aliasMap) { public static ZoneId of(String zoneId, Map<String, String> aliasMap) {
Objects.requireNonNull(zoneId, "zoneId"); Objects.requireNonNull(zoneId, "zoneId");
Objects.requireNonNull(aliasMap, "aliasMap"); Objects.requireNonNull(aliasMap, "aliasMap");
String id = aliasMap.get(zoneId); String id = Objects.requireNonNullElse(aliasMap.get(zoneId), zoneId);
id = (id != null ? id : zoneId);
return of(id); return of(id);
} }

View File

@ -177,7 +177,7 @@ public interface Chronology extends Comparable<Chronology> {
static Chronology from(TemporalAccessor temporal) { static Chronology from(TemporalAccessor temporal) {
Objects.requireNonNull(temporal, "temporal"); Objects.requireNonNull(temporal, "temporal");
Chronology obj = temporal.query(TemporalQueries.chronology()); Chronology obj = temporal.query(TemporalQueries.chronology());
return (obj != null ? obj : IsoChronology.INSTANCE); return Objects.requireNonNullElse(obj, IsoChronology.INSTANCE);
} }
//----------------------------------------------------------------------- //-----------------------------------------------------------------------

View File

@ -2892,7 +2892,8 @@ public final class DateTimeFormatterBuilder {
@Override @Override
public String toString() { public String toString() {
return "ReducedValue(" + field + "," + minWidth + "," + maxWidth + "," + (baseDate != null ? baseDate : baseValue) + ")"; return "ReducedValue(" + field + "," + minWidth + "," + maxWidth +
"," + Objects.requireNonNullElse(baseDate, baseValue) + ")";
} }
} }
@ -3851,6 +3852,10 @@ public final class DateTimeFormatterBuilder {
return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO); return parseOffsetBased(context, text, position, position + 2, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
} else if (context.charEquals(nextChar, 'G') && length >= position + 3 && } else if (context.charEquals(nextChar, 'G') && length >= position + 3 &&
context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) { context.charEquals(nextNextChar, 'M') && context.charEquals(text.charAt(position + 2), 'T')) {
if (length >= position + 4 && context.charEquals(text.charAt(position + 3), '0')) {
context.setParsed(ZoneId.of("GMT0"));
return position + 4;
}
return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO); return parseOffsetBased(context, text, position, position + 3, OffsetIdPrinterParser.INSTANCE_ID_ZERO);
} }
} }
@ -4328,7 +4333,7 @@ public final class DateTimeFormatterBuilder {
private String getChronologyName(Chronology chrono, Locale locale) { private String getChronologyName(Chronology chrono, Locale locale) {
String key = "calendarname." + chrono.getCalendarType(); String key = "calendarname." + chrono.getCalendarType();
String name = DateTimeTextProvider.getLocalizedResource(key, locale); String name = DateTimeTextProvider.getLocalizedResource(key, locale);
return name != null ? name : chrono.getId(); return Objects.requireNonNullElseGet(name, () -> chrono.getId());
} }
} }

View File

@ -146,7 +146,7 @@ final class DateTimePrintContext {
if (overrideZone != null) { if (overrideZone != null) {
// if have zone and instant, calculation is simple, defaulting chrono if necessary // if have zone and instant, calculation is simple, defaulting chrono if necessary
if (temporal.isSupported(INSTANT_SECONDS)) { if (temporal.isSupported(INSTANT_SECONDS)) {
Chronology chrono = (effectiveChrono != null ? effectiveChrono : IsoChronology.INSTANCE); Chronology chrono = Objects.requireNonNullElse(effectiveChrono, IsoChronology.INSTANCE);
return chrono.zonedDateTime(Instant.from(temporal), overrideZone); return chrono.zonedDateTime(Instant.from(temporal), overrideZone);
} }
// block changing zone on OffsetTime, and similar problem cases // block changing zone on OffsetTime, and similar problem cases

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -102,7 +102,7 @@ import sun.util.locale.provider.LocaleResources;
* The complete date is expressed using three fields: * The complete date is expressed using three fields:
* <ul> * <ul>
* <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92 * <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92
* <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the week within the week-based-year * <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4
* <li>{@link ChronoField#YEAR YEAR} - the standard ISO year * <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
* </ul> * </ul>
* *
@ -571,9 +571,6 @@ public final class IsoFields {
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274}; private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274};
private static boolean isIso(TemporalAccessor temporal) {
return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
}
private static void ensureIso(TemporalAccessor temporal) { private static void ensureIso(TemporalAccessor temporal) {
if (isIso(temporal) == false) { if (isIso(temporal) == false) {
@ -681,7 +678,7 @@ public final class IsoFields {
@Override @Override
public boolean isSupportedBy(Temporal temporal) { public boolean isSupportedBy(Temporal temporal) {
return temporal.isSupported(EPOCH_DAY); return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -721,4 +718,8 @@ public final class IsoFields {
return name; return name;
} }
} }
static boolean isIso(TemporalAccessor temporal) {
return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
}
} }

View File

@ -2882,6 +2882,7 @@ public class Arrays {
* @param a2 the other array to be tested for equality * @param a2 the other array to be tested for equality
* @return {@code true} if the two arrays are equal * @return {@code true} if the two arrays are equal
*/ */
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] a, byte[] a2) { public static boolean equals(byte[] a, byte[] a2) {
if (a==a2) if (a==a2)
return true; return true;

View File

@ -2090,7 +2090,8 @@ public class Collections {
* through the returned set.<p> * through the returned set.<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* set when iterating over it: * collection when traversing it via {@link Iterator}, {@link Spliterator}
* or {@link Stream}:
* <pre> * <pre>
* Set s = Collections.synchronizedSet(new HashSet()); * Set s = Collections.synchronizedSet(new HashSet());
* ... * ...
@ -2149,8 +2150,9 @@ public class Collections {
* through the returned sorted set (or its views).<p> * through the returned sorted set (or its views).<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* sorted set when iterating over it or any of its {@code subSet}, * sorted set when traversing it or any of its {@code subSet},
* {@code headSet}, or {@code tailSet} views. * {@code headSet}, or {@code tailSet} views via {@link Iterator},
* {@link Spliterator} or {@link Stream}:
* <pre> * <pre>
* SortedSet s = Collections.synchronizedSortedSet(new TreeSet()); * SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
* ... * ...
@ -2240,8 +2242,9 @@ public class Collections {
* accomplished through the returned navigable set (or its views).<p> * accomplished through the returned navigable set (or its views).<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* navigable set when iterating over it or any of its {@code subSet}, * navigable set when traversing it, or any of its {@code subSet},
* {@code headSet}, or {@code tailSet} views. * {@code headSet}, or {@code tailSet} views, via {@link Iterator},
* {@link Spliterator} or {@link Stream}:
* <pre> * <pre>
* NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet()); * NavigableSet s = Collections.synchronizedNavigableSet(new TreeSet());
* ... * ...
@ -2355,7 +2358,8 @@ public class Collections {
* through the returned list.<p> * through the returned list.<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* list when iterating over it: * list when traversing it via {@link Iterator}, {@link Spliterator}
* or {@link Stream}:
* <pre> * <pre>
* List list = Collections.synchronizedList(new ArrayList()); * List list = Collections.synchronizedList(new ArrayList());
* ... * ...
@ -2523,7 +2527,8 @@ public class Collections {
* through the returned map.<p> * through the returned map.<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* map when iterating over any of its collection views: * map when traversing any of its collection views via {@link Iterator},
* {@link Spliterator} or {@link Stream}:
* <pre> * <pre>
* Map m = Collections.synchronizedMap(new HashMap()); * Map m = Collections.synchronizedMap(new HashMap());
* ... * ...
@ -2700,9 +2705,10 @@ public class Collections {
* through the returned sorted map (or its views).<p> * through the returned sorted map (or its views).<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* sorted map when iterating over any of its collection views, or the * sorted map when traversing any of its collection views, or the
* collections views of any of its {@code subMap}, {@code headMap} or * collections views of any of its {@code subMap}, {@code headMap} or
* {@code tailMap} views. * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
* {@link Stream}:
* <pre> * <pre>
* SortedMap m = Collections.synchronizedSortedMap(new TreeMap()); * SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
* ... * ...
@ -2797,9 +2803,10 @@ public class Collections {
* accomplished through the returned navigable map (or its views).<p> * accomplished through the returned navigable map (or its views).<p>
* *
* It is imperative that the user manually synchronize on the returned * It is imperative that the user manually synchronize on the returned
* navigable map when iterating over any of its collection views, or the * navigable map when traversing any of its collection views, or the
* collections views of any of its {@code subMap}, {@code headMap} or * collections views of any of its {@code subMap}, {@code headMap} or
* {@code tailMap} views. * {@code tailMap} views, via {@link Iterator}, {@link Spliterator} or
* {@link Stream}:
* <pre> * <pre>
* NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap()); * NavigableMap m = Collections.synchronizedNavigableMap(new TreeMap());
* ... * ...

View File

@ -49,6 +49,7 @@ import java.text.DecimalFormatSymbols;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.Objects;
import java.time.DateTimeException; import java.time.DateTimeException;
import java.time.Instant; import java.time.Instant;
@ -3860,7 +3861,7 @@ public final class Formatter implements Closeable, Flushable {
ampm = dfs.getAmPmStrings(); ampm = dfs.getAmPmStrings();
} }
String s = ampm[t.get(Calendar.AM_PM)]; String s = ampm[t.get(Calendar.AM_PM)];
sb.append(s.toLowerCase(l != null ? l : Locale.US)); sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@ -3893,7 +3894,7 @@ public final class Formatter implements Closeable, Flushable {
TimeZone tz = t.getTimeZone(); TimeZone tz = t.getTimeZone();
sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0), sb.append(tz.getDisplayName((t.get(Calendar.DST_OFFSET) != 0),
TimeZone.SHORT, TimeZone.SHORT,
(l == null) ? Locale.US : l)); Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
@ -3901,7 +3902,7 @@ public final class Formatter implements Closeable, Flushable {
case DateTime.NAME_OF_DAY_ABBREV: // 'a' case DateTime.NAME_OF_DAY_ABBREV: // 'a'
case DateTime.NAME_OF_DAY: { // 'A' case DateTime.NAME_OF_DAY: { // 'A'
int i = t.get(Calendar.DAY_OF_WEEK); int i = t.get(Calendar.DAY_OF_WEEK);
Locale lt = ((l == null) ? Locale.US : l); Locale lt = Objects.requireNonNullElse(l, Locale.US);
DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
if (c == DateTime.NAME_OF_DAY) if (c == DateTime.NAME_OF_DAY)
sb.append(dfs.getWeekdays()[i]); sb.append(dfs.getWeekdays()[i]);
@ -3913,7 +3914,7 @@ public final class Formatter implements Closeable, Flushable {
case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
case DateTime.NAME_OF_MONTH: { // 'B' case DateTime.NAME_OF_MONTH: { // 'B'
int i = t.get(Calendar.MONTH); int i = t.get(Calendar.MONTH);
Locale lt = ((l == null) ? Locale.US : l); Locale lt = Objects.requireNonNullElse(l, Locale.US);
DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
if (c == DateTime.NAME_OF_MONTH) if (c == DateTime.NAME_OF_MONTH)
sb.append(dfs.getMonths()[i]); sb.append(dfs.getMonths()[i]);
@ -3984,7 +3985,7 @@ public final class Formatter implements Closeable, Flushable {
StringBuilder tsb = new StringBuilder(); StringBuilder tsb = new StringBuilder();
print(tsb, t, DateTime.AM_PM, l); print(tsb, t, DateTime.AM_PM, l);
sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999)
@ -4092,7 +4093,7 @@ public final class Formatter implements Closeable, Flushable {
ampm = dfs.getAmPmStrings(); ampm = dfs.getAmPmStrings();
} }
String s = ampm[t.get(ChronoField.AMPM_OF_DAY)]; String s = ampm[t.get(ChronoField.AMPM_OF_DAY)];
sb.append(s.toLowerCase(l != null ? l : Locale.US)); sb.append(s.toLowerCase(Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?)
@ -4131,7 +4132,7 @@ public final class Formatter implements Closeable, Flushable {
sb.append(TimeZone.getTimeZone(zid.getId()) sb.append(TimeZone.getTimeZone(zid.getId())
.getDisplayName(zid.getRules().isDaylightSavings(instant), .getDisplayName(zid.getRules().isDaylightSavings(instant),
TimeZone.SHORT, TimeZone.SHORT,
(l == null) ? Locale.US : l)); Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
sb.append(zid.getId()); sb.append(zid.getId());
@ -4141,7 +4142,7 @@ public final class Formatter implements Closeable, Flushable {
case DateTime.NAME_OF_DAY_ABBREV: // 'a' case DateTime.NAME_OF_DAY_ABBREV: // 'a'
case DateTime.NAME_OF_DAY: { // 'A' case DateTime.NAME_OF_DAY: { // 'A'
int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1; int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1;
Locale lt = ((l == null) ? Locale.US : l); Locale lt = Objects.requireNonNullElse(l, Locale.US);
DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
if (c == DateTime.NAME_OF_DAY) if (c == DateTime.NAME_OF_DAY)
sb.append(dfs.getWeekdays()[i]); sb.append(dfs.getWeekdays()[i]);
@ -4153,7 +4154,7 @@ public final class Formatter implements Closeable, Flushable {
case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b
case DateTime.NAME_OF_MONTH: { // 'B' case DateTime.NAME_OF_MONTH: { // 'B'
int i = t.get(ChronoField.MONTH_OF_YEAR) - 1; int i = t.get(ChronoField.MONTH_OF_YEAR) - 1;
Locale lt = ((l == null) ? Locale.US : l); Locale lt = Objects.requireNonNullElse(l, Locale.US);
DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt);
if (c == DateTime.NAME_OF_MONTH) if (c == DateTime.NAME_OF_MONTH)
sb.append(dfs.getMonths()[i]); sb.append(dfs.getMonths()[i]);
@ -4223,7 +4224,7 @@ public final class Formatter implements Closeable, Flushable {
// this may be in wrong place for some locales // this may be in wrong place for some locales
StringBuilder tsb = new StringBuilder(); StringBuilder tsb = new StringBuilder();
print(tsb, t, DateTime.AM_PM, l); print(tsb, t, DateTime.AM_PM, l);
sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); sb.append(tsb.toString().toUpperCase(Objects.requireNonNullElse(l, Locale.US)));
break; break;
} }
case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999)

View File

@ -295,7 +295,7 @@ public final class Objects {
* {@code defaultObj} is {@code null} * {@code defaultObj} is {@code null}
* @since 9 * @since 9
*/ */
public static <T> T nonNullElse(T obj, T defaultObj) { public static <T> T requireNonNullElse(T obj, T defaultObj) {
return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj"); return (obj != null) ? obj : requireNonNull(defaultObj, "defaultObj");
} }
@ -314,8 +314,9 @@ public final class Objects {
* the {@code supplier.get()} value is {@code null} * the {@code supplier.get()} value is {@code null}
* @since 9 * @since 9
*/ */
public static <T> T nonNullElseGet(T obj, Supplier<? extends T> supplier) { public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier) {
return (obj != null) ? obj : requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()"); return (obj != null) ? obj
: requireNonNull(requireNonNull(supplier, "supplier").get(), "supplier.get()");
} }
/** /**

View File

@ -34,7 +34,7 @@ import java.util.stream.IntStream;
import java.util.stream.LongStream; import java.util.stream.LongStream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import sun.misc.Unsafe; import jdk.internal.misc.Unsafe;
/** /**
* An instance of this class is used to generate a stream of * An instance of this class is used to generate a stream of

View File

@ -2775,7 +2775,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
} }
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long RESULT; private static final long RESULT;
private static final long STACK; private static final long STACK;
private static final long NEXT; private static final long NEXT;

View File

@ -297,7 +297,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
* Table accesses require volatile/atomic reads, writes, and * Table accesses require volatile/atomic reads, writes, and
* CASes. Because there is no other way to arrange this without * CASes. Because there is no other way to arrange this without
* adding further indirections, we use intrinsics * adding further indirections, we use intrinsics
* (sun.misc.Unsafe) operations. * (jdk.internal.misc.Unsafe) operations.
* *
* We use the top (sign) bit of Node hash fields for control * We use the top (sign) bit of Node hash fields for control
* purposes -- it is available anyway because of addressing * purposes -- it is available anyway because of addressing
@ -3287,7 +3287,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
return true; return true;
} }
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long LOCKSTATE; private static final long LOCKSTATE;
static { static {
try { try {
@ -6330,7 +6330,7 @@ public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
} }
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long SIZECTL; private static final long SIZECTL;
private static final long TRANSFERINDEX; private static final long TRANSFERINDEX;
private static final long BASECOUNT; private static final long BASECOUNT;

View File

@ -326,7 +326,7 @@ public class ConcurrentLinkedDeque<E>
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long PREV; private static final long PREV;
private static final long ITEM; private static final long ITEM;
private static final long NEXT; private static final long NEXT;
@ -1608,7 +1608,7 @@ public class ConcurrentLinkedDeque<E>
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long HEAD; private static final long HEAD;
private static final long TAIL; private static final long TAIL;
static { static {

View File

@ -929,7 +929,7 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long HEAD; private static final long HEAD;
private static final long TAIL; private static final long TAIL;
private static final long ITEM; private static final long ITEM;

View File

@ -534,7 +534,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long VALUE; private static final long VALUE;
private static final long NEXT; private static final long NEXT;
@ -614,7 +614,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
} }
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long RIGHT; private static final long RIGHT;
static { static {
try { try {
@ -3596,7 +3596,7 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
} }
// Unsafe mechanics // Unsafe mechanics
private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe(); private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
private static final long HEAD; private static final long HEAD;
static { static {
try { try {

Some files were not shown because too many files have changed in this diff Show More